Trying to create a new Active Directory user, Invoke("SetPassword",pwd) throws "The RPC server is unavailable"
I'm trying to create a new user on my development active directory server using .NET System.DirectoryServices namespace.
I try using the following code:
DirectoryEntry dirEntry = new DirectoryEntry(path, "TESTDOM\\Administrator", "2109password", AuthenticationTypes.Secure | AuthenticationTypes.ServerBind);
object o = dirEntry.NativeObject;
DirectoryEntry newUser = dirEntry.Children.Add("CN=NewUser4", "user");
newUser.Properties["samAccountName"].Value = "NewUser4";
newUser.Properties["Description"].Add("User Description");
newUser.Invoke("SetPassword", new object[] {"2109password"} );
newUser.CommitChanges();
I also tried committing using
newUser.CommitChanges();
before I call the Invoke to set the password. I always get a TargetInvocationException wrapping:
InnerException {"The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)"} System.Exception {System.Runtime.InteropServices.COMException}
The exception is always only thrown when I call
newUser.Invoke("SetPassword", new object[] {"2109password"} );
If I call newUser.CommitChanges() before I try to call In开发者_如何学Cvoke with SetPassword, the new user is created on the domain. I can then go manually to the AD machine and set the same password with no problems (so it's not a problem with the password string being against the rules). I've notice many post online about this but found no solution.
I think it might have something to do with the fact that the machine running the code is not a member in the domain. Although the user TESTDOM\Administrator is a member of the: administrators, domain admins, schema admin and enterprise admins groups on the TESTDOM domain.
Notice that I can't use System.DirectoryServices.AccountManagement namespace as I'm working with .NET 2 Any ideas on what can I do to solve this? I am desperate
I guess you need to create the user first before setting properties to it, I usually do it by
/// <summary>
/// This Method will Create a new User Directory Object based on a Username and LDAP Domain
/// </summary>
/// <param name="sUserName">The Username of the New User</param>
/// <param name="sLDAPDomain">The LDAP Domain for the New User</param>
/// <returns></returns>
public DirectoryEntry CreateNewUser(string sUserName, string sLDAPDomain)
{
//Set the LDAP qualification so that the user will be Created under the Users Container
string LDAPDomain = "/CN=Users," + sLDAPDomain;
oDE = new DirectoryEntry("LDAP://" + sADServer + "/" + sLDAPDomain, sADUser, sADPassword, AuthenticationTypes.Secure);
oDEC = oDE.Children.Add("CN=" + sUserName, "user");
oDE.Close();
return oDEC;
}
then set any properties I need
/// <summary>
/// This will Set the Property of the Directory Entry Object
/// </summary>
/// <param name="oDE">The Directory Object to Set to</param>
/// <param name="sPropertyName">The Property Name</param>
/// <param name="sPropertyValue">The Property Value</param>
public void SetProperty(DirectoryEntry oDE, string sPropertyName, string sPropertyValue)
{
//Check if the Value is Valid
if (sPropertyValue != string.Empty)
{
//Check if the Property Exists
if (oDE.Properties.Contains(sPropertyName))
{
oDE.Properties[sPropertyName].Value = sPropertyValue;
oDE.CommitChanges();
oDE.Close();
}
else
{
oDE.Properties[sPropertyName].Add(sPropertyValue);
oDE.CommitChanges();
oDE.Close();
}
}
}
then set the password
/// <summary>
/// This Method will set the Users Password based on Directory Entry Object
/// </summary>
/// <param name="oDE">The Directory Entry to Set the New Password</param>
/// <param name="sPassword">The New Password</param>
/// <param name="sMessage">Any Messages catched by the Exception</param>
public void SetUserPassword(DirectoryEntry oDE, string sPassword, out string sMessage)
{
try
{
//Set The new Password
oDE.Invoke("SetPassword", new Object[] { sPassword });
sMessage = "";
oDE.CommitChanges();
oDE.Close();
}
catch (Exception ex)
{
sMessage = ex.InnerException.Message;
}
}
And finally enable the account
/// <summary>
/// This Method will Enable a User Account Based on the Directory Entry Object
/// </summary>
/// <param name="oDE">The Directoy Entry Object of the Account to Enable</param>
public void EnableUserAccount(DirectoryEntry oDE)
{
oDE.Properties["userAccountControl"][0] = ADMethods.ADAccountOptions.UF_NORMAL_ACCOUNT;
oDE.CommitChanges();
oDE.Close();
}
For a full implementation you can go here -> http://anyrest.wordpress.com/2010/02/01/active-directory-objects-and-c/
OK, I got it working:
dirEntry = new DirectoryEntry(ldapPath, domainAdminUser, domainAdminPassword);
dirEntry.Invoke("SetPassword", new object[] { newPassword });
dirEntry.Properties["LockOutTime"].Value = 0; //unlock account
ldapPath should include the full DN of the user we're trying to change , so it should look something like:
string ldapPath = "LDAP://ad.domain.com:389/CN=username,OU=Users,DC=ad,DC=domain,DC=com"
You are right that you need to create the account first and then call SetPassword. You can try to use Invoke SetInfo instead of CommitChanges and then SetPassword.
If that doesn't work as well my guess is that you are not setting a required property such as displayName.
精彩评论