私が働いている会社には、ユーザー名、名、姓、OU1、OU2 などの入力情報に基づいて新しい Active Directory アカウントを作成できる Web サービスがあります。
この Web サービスは、Windows Server 2003 で正常に動作しています。現在、Web サービスを 2008 R2 サーバーに移行する作業を行っています。ただし、新しく作成されたアカウントにランダムな初期パスワードを設定しようとすると、特定の機能が機能しなくなります。
スローされる例外は、「RPC サーバーを利用できません」というメッセージを含む COMException の内部例外を含む TargetInvocationException です。
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...
これには古いコードと新しいコードが混在していますが、新しいサーバーではうまく機能しているようです。注意すべきことの 1 つは、UserPrincipal.FindByIdentity 呼び出しが最初に Nothing を返す場合があることです。これは、アカウントの作成またはレプリケーションの遅延が原因であると考えられます。そのため、オブジェクトを取得するまで FindByIdentity を複数回試行して、ユーザー オブジェクトが Nothing でないことを確認する必要があります。
問題の解決策 (回避方法のようなもの) を見つけたにもかかわらず、古いコードが新しいサーバーでは機能しないのに、新しいサーバーでは機能する理由についてまだ混乱しています。エラーは非常に一般的なものであり、インターネットで手がかりを検索すると、混乱が生じるだけです。
そこの専門家がいくつかの光を当てるか、私の新しいコードがどのように見えるかについてコメントすることさえできれば、本当に感謝します。問題はありますか?
前もって感謝します。