C# 将用户添加到 Active Directory - 指定给目录服务的属性语法无效

Posted

技术标签:

【中文标题】C# 将用户添加到 Active Directory - 指定给目录服务的属性语法无效【英文标题】:C# Add User to Active Directory - The attribute syntax specified to the directory service is invalid 【发布时间】:2014-06-12 20:18:27 【问题描述】:

尝试在 Active Directory 中创建新用户时遇到问题。我按照link 中提供的步骤使用 PrincipalContext(除了我一次只做一个用户,当他们被雇用并进入系统而不是多个用户,所以不需要循环)。我也在使用 UserPrincipal 扩展器。

这是我的代码:

protected void CreateUserPE()

    try
    
        PrincipalContext userCtx = new PrincipalContext(ContextType.Domain, DomainFQDN, DomainFull);
        string UserName = txtFirstName.Text.ToLower() + " " + txtLastName.Text.ToLower();
        string password = "superSecretPassword";

        UserPrincipalsEx newUser = new UserPrincipalsEx(userCtx, UserName, password, true);
        newUser.SamAccountName = txtFirstName.Text.ToLower() + "." + txtLastName.Text.ToLower();
        newUser.UserPrincipalName = txtFirstName.Text.ToLower() + "." + txtLastName.Text.ToLower() + "@rasm.com";
        newUser.EmployeeId = txtEmpID.Text;
        newUser.LastName = txtLastName.Text;
        newUser.GivenName = txtFirstName.Text;
        newUser.DisplayName = txtFirstName.Text + " " + txtLastName.Text;
        newUser.Name = txtFirstName.Text + " " + txtLastName.Text;
        newUser.SetPassword(password);
        newUser.HomePostalAddress = txtAddress.Text + ", " + txtCity.Text + ", " + txtState.Text + ", " + txtZip.Text;
        newUser.CountryName = txtCountry.Text;
        newUser.HomePhone = txtHomePhone.Text;
        newUser.MobilePhone = txtMobilePhone.Text;
        newUser.DateOfBirth = txtDOB.Text;
        newUser.EmergencyContact = txtEmergencyCnt.Text;
        newUser.EmergencyPhone = txtContactPhone.Text;
        newUser.Relationship = ddlRelationship1.SelectedItem.ToString();
        newUser.EmergencyContact2 = txtEmergencyCnt2.Text;
        newUser.EmergencyPhone2 = txtContactPhone2.Text;
        newUser.Relationship2 = ddlRelationship2.SelectedItem.ToString();
        newUser.EyeColor = ddlEyeColor.SelectedItem.ToString();
        newUser.HairColor = ddlHairColor.SelectedItem.ToString();
        newUser.Height = txtHeight.Text;
        newUser.Weight = txtWeight.Text;
        newUser.Gender = ddlGender.SelectedItem.ToString();
        newUser.PersonalEmail = txtPersonalEmail.Text;
        newUser.PassportExpires = txtPassportExp.Text;
        newUser.HomeBase = ddlHomeStation.SelectedItem.ToString();
        newUser.WorkLocation = txtWorkLocation.Text;
        newUser.PID = txtPID.Text;
        newUser.Team = txtTeam.Text;
        newUser.Manager = "CN=" + txtSupervisor.Text + "," + DomainFull;
        newUser.Title = ddlJobTitle.SelectedItem.ToString();
        newUser.JobCode = txtJobCode.Text;
        newUser.PLC = txtPLC.Text;
        newUser.BPLC = txtBPLC.Text;
        newUser.Specialty = txtSpecialty.Text;
        newUser.Position = txtPosition.Text;
        newUser.DateOfHire = txtDOH.Text;
        newUser.DateOnContract = txtDOC.Text;
        newUser.TaskOrder = ddlTaskOrder.SelectedItem.ToString();
        newUser.Classification = ddlClass.SelectedIndex.ToString();
        newUser.Section = txtSection.Text;
        newUser.GatePass = txtGatePass.Text;
        newUser.GatePassExpires = txtGatePassExp.Text;
        newUser.WorkPhone = txtWorkPhone.Text;
        newUser.CompanyEmail = txtCompEmail.Text;
        newUser.aKOEmail = txtMilEmail.Text;
        newUser.aKOSponsor = txtMilEmailSp.Text;
        newUser.CACSponsor = txtCacSponsor.Text;
        newUser.CACSponsorEmail = txtCacSponsorEmail.Text;
        newUser.CacCardExpires = txtCacExpires.Text;
        newUser.Enabled = true;
        newUser.ExpirePasswordNow();
        newUser.Save();
        newUser.Dispose();
    
    catch
    

    

程序一直到newUser.Save()然后在catch语句中抛出如下错误:

System.DirectoryServices.AccountManagement.PrincipalOperationException was caught
  HResult=-2146233087
  Message=The attribute syntax specified to the directory service is invalid.

  Source=System.DirectoryServices.AccountManagement
  ErrorCode=-2147016693
  StackTrace:
   at System.DirectoryServices.AccountManagement.ADStoreCtx.Insert(Principal p)
   at System.DirectoryServices.AccountManagement.Principal.Save()
   at Personnel_Employee.CreateUserPE() in c:\inetpub\wwwroot\TestingFolder\Personnel\Add\Employee.aspx.cs:line 263
   InnerException: System.DirectoryServices.DirectoryServicesCOMException
   HResult=-2147016693
   Message=The attribute syntax specified to the directory service is invalid.

   Source=System.DirectoryServices
   ErrorCode=-2147016693
   ExtendedError=87
   ExtendedErrorMessage=00000057: LdapErr: DSID-0C090D11, comment: Error in attribute conversion operation, data 0, v23f0
   StackTrace:
        at System.DirectoryServices.DirectoryEntry.CommitChanges()
        at System.DirectoryServices.AccountManagement.SDSUtils.ApplyChangesToDirectory(Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes)
   InnerException: 

我哪里错了。

【问题讨论】:

newUser.Save() 抛出异常?这有点无聊,但你能提供用“...更多类似代码...”替换的行吗?我怀疑问题出在属性语法上。 我按照您的要求进行了编辑。大多数属性是通过 MMC.EXE 自定义添加到 Active Directory 中的。我将所有自定义的设置为“Unicode 字符串”的语法。我还创建了一个名为 UserPrincipalsEx.cs 的类来扩展默认情况下不可用的所有属性。” 我想我明白了。 UserPrincipalsEx 已声明:class UserPrincipalsEx : UserPrincipal ? public class UserPrincipalsEx : UserPrincipal public UserPrincipalsEx(PrincipalContext context) : base(context) public UserPrincipalsEx(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password , 启用) 您是否知道您必须使用属性映射您的类属性与 Active-Directory 属性? 【参考方案1】:

您不能使用 null 或空来更新属性。我个人不喜欢具有虚拟值的解决方案。如果您使用上下文原则,只需检查 null 或空,如果是这种情况,请不要更新:

if (!string.IsNullOrEmpty(txtbox.Text)) newUser.attributeName = txtbox.Text

如果您使用的是目录条目而不是用户上下文,您可以执行以下操作:

string adPath = "LDAP://server.domain.com/CN=John,CN=Users,dc=domain,dc=com";
DirectoryEntry userEntry = new DirectoryEntry(adPath);
if (txtBox.text == "")

    userEntry.Properties["proppertyName"].Clear();

else if (!string.IsNullOrEmpty(txtBox.text))

    userEntry.Properties[attribute.Key].Value = txtBox.text;

// dont do a thing when txtBox.Text is empty

它看起来像更多的代码,但如果你有一个包含所有属性的列表,那么为它创建一个 foreachloop 会更容易:

private void UpdateEntryAttributes(DirectoryEntry entry, Dictionary<string, string> attributes)

    foreach (KeyValuePair<string, string> attribute in attributes)
    
    entry.Properties[attribute.Key].Value = attribute.Value;

    if (attribute.Value == "")
    
        entry.Properties[attribute.Key].Clear();
    
    else if (!string.IsNullOrEmpty(attribute.Value))
    
        entry.Properties[attribute.Key].Value = attribute.Value;
    

【讨论】:

【参考方案2】:

当尝试将 null 或空字符串写入禁止它的 AD 字段时,可能会发生这种情况。检查这是否是问题的一种简单方法是用虚拟字符串(长度> 0)临时替换所有这些值,然后再次运行代码。如果可行,您可以尝试通过更改违规值来进行修复——使用 AD,有时如果 null 不起作用,则空字符串将起作用,反之亦然。

【讨论】:

Arrrrgh,属性为 null 或空字符串。谢谢你张贴这个!试图找出神秘的 AD 错误消息真是令人沮丧。点赞! 它没有提到什么属性,确实很有帮助的消息......

以上是关于C# 将用户添加到 Active Directory - 指定给目录服务的属性语法无效的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell:如何将 1 个用户添加到多个 Active Directory 安全组 - 具有写入权限的安全组的安全选项卡

在 C# 中验证远程 Active Directory 的用户

在 .NET 中的 Active Directory 组中添加和删除用户

在 C# 中搜索 Active Directory 并使用当前用户进行身份验证

从非托管 C++ mfc active x dll 启动 C# 对话框

通过 C# 删除 Active Directory 中的用户