title: Using DirectoryEntry.Invoke("SetPassword", ...) to set initial AD account password, I get "RPC server is unavailable" error
body: <p>The company I'm working in has a web service that can create new Active Directory accounts based on information that is typed in e.g. username, firstname, lastname, OU1, OU2, etc.</p>
  
  <p>This web service has been working fine on Windows Server 2003. Now I'm working on moving the web service to 2008 R2 servers. However a certain functionality doesn't work anymore, which is when it tries to set a random initial password to the newly created account.</p>
  
  <p>The exception that is thrown is a TargetInvocationException containing an inner exception of COMException with a message of "The RPC Server is unavailable".</p>
  
  <pre><code>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=" &amp; 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...
  </code></pre>
  
  <p>The error happens on the line that says:
  objUser.Invoke("SetPassword", New Object() {strPassword})</p>
  
  <p>Strangely the account creation itself works and I can see the new user from Active Directory Users and Computers.
  I have consulted a few different people who manage the security of the DCs and the web servers, they don't really know why...</p>
  
  <p>In the end I figured out a different way of setting the password, which is using the System.DirectoryServices.AccountManagement library.</p>
  
  <p>So the code becomes something like this:</p>
  
  <pre><code>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=" &amp; 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...
  </code></pre>
  
  <p>I'm mixing old code with new code in this one, but it appears to be working really well on the new servers. One thing to note is that sometimes the UserPrincipal.FindByIdentity call initially returns Nothing, I believe due to delay in the account creation or with the replication. So I have to make sure that the user object is not Nothing by trying FindByIdentity multiple times until I get the object.</p>
  
  <p>Despite finding a solution (more like a way around) to the problem, still I'm confused as to why the old code does not work on the new servers, but the new one does. The error is very generic and searching the internet for clues have resulted in nothing but more confusion.</p>
  
  <p>Would really appreciate if experts out there can shed some lights or even comment on the way my new code looks, any problems?</p>
  
  <p>Thanks in advance.</p>