1

我工作的公司有一个 Web 服务,可以根据输入的信息创建新的 Active Directory 帐户,例如用户名、名字、姓氏、OU1、OU2 等。

此 Web 服务在 Windows Server 2003 上运行良好。现在我正在努力将 Web 服务移至 2008 R2 服务器。但是,某些功能不再起作用,即当它尝试为新创建的帐户设置随机初始密码时。

引发的异常是 TargetInvocationException,其中包含 COMException 的内部异常,并带有“RPC 服务器不可用”消息。

Imports System.DirectoryServices

Dim ldapPath As String = "..." 'assume valid LDAP path
Dim objContainer As DirectoryEntry = New DirectoryEntry(ldapPath, vbNullString, vbNullString, AuthenticationTypes.Secure)
objUser = objContainer.Children.Add("cn=" & Username.Trim, "user")

'sets objUser.Properties e.g. givenName, displayName, userPrincipalName, samAccountName, etc. Not important...
objUser.CommitChanges()

strPassword = RandomPassword()  'function that generates random password
objUser.Invoke("SetPassword", New Object() {strPassword})

objUser.Properties("useraccountcontrol").Value = "512" ' set as normal account
objUser.CommitChanges()

'and so on...

错误发生在以下行: objUser.Invoke("SetPassword", New Object() {strPassword})

奇怪的是,帐户创建本身有效,我可以从 Active Directory 用户和计算机中看到新用户。我咨询了几个管理 DC 和 Web 服务器安全性的人,他们真的不知道为什么......

最后,我想出了另一种设置密码的方法,即使用 System.DirectoryServices.AccountManagement 库。

所以代码变成了这样:

Imports System.DirectoryServices
Imports System.DirectoryServices.AccountManagement

Dim ldapPath As String = "..." 'assume valid LDAP path
Dim objContainer As DirectoryEntry = New DirectoryEntry(ldapPath, vbNullString, vbNullString, AuthenticationTypes.Secure)
Dim objUser As DirectoryEntry = objContainer.Children.Add("cn=" & Username.Trim, "user")

'sets objUser.Properties e.g. givenName, displayName, userPrincipalName, samAccountName, etc. Not important...
objUser.CommitChanges()

Dim domainContext As PrincipalContext = New PrincipalContext(ContextType.Domain, ...)
Dim user As UserPrincipal = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, Trim(Username))

strPassword = RandomPassword()  'function that generates random password
user.SetPassword(strPassword)

user.Enabled = True                 'setting these two properties
user.PasswordNotRequired = False    'result in useraccountcontrol value = 512 (normal account)
user.Save()

'and so on...

我将旧代码与新代码混合在一起,但它似乎在新服务器上运行良好。需要注意的一件事是,有时 UserPrincipal.FindByIdentity 调用最初会返回 Nothing,我相信这是由于帐户创建或复制延迟所致。所以我必须通过多次尝试 FindByIdentity 来确保用户对象不是 Nothing,直到我得到对象。

尽管找到了解决问题的方法(更像是一种解决方法),但我仍然对为什么旧代码不能在新服务器上运行而感到困惑,但新代码却可以。该错误非常普遍,在互联网上搜索线索只会导致更多混乱。

如果那里的专家可以阐明一些观点,甚至评论我的新代码的外观,我会非常感激,有什么问题吗?

提前致谢。

4

0 回答 0