DirectoryEntry Exception when calling Invoke(“SetPassword”,…)

I wrote a blog a few months ago about a COMException I got when I attempted to call DirectoryEntry.Invoke(“SetPassword”, …). The issue was that I could set the password for one account but then subsequent set password attempts would throw an exception. I had contacted Microsoft and they informed me that I was only the second person ever to report the problem, and that is was intermittent at best for the previous report. Microsoft had, and to this day still does not, have a hotfix for this issue.
After testing and trying a lot of ideas I thought I had resolved the issue by just capturing the exception and continuing on in my code (later calls would set account enabled and commit, etc). However, when we deployed the solution we quickly realized our test environment was able to create the account more regularly than our production environment. Therefore our testers were able to create account with valid password and log into the test environment, but production users were getting invalid passwords.
I started looking back through our system and SharePoint logs and realized I was still having the COMException get thrown and that the password change was not getting committed later in the process, our lost password utility really triggered this since both the account provisioner and lost password used the same logic for setting the password. Microsoft had told me that when the first caller notified them of this issue they were able to reset IIS and the issue was resolved.
Although this is a high availability environment, we really couldn’t afford resetting our IIS on the server every time a new account was created. Instead I realized that I could push the DirectoryEntry.Invoke(“SetPassword”, …) into a web service and allow my provisioning code to use that. Each time a web service was called it essentially created a new process to handle the service request, and when complete the process would effectively terminate.
Just to make sure this issue could also be worked around I added a Application Pool Recycle, basically a restart of an IIS Web Application, so that if it did fail we could restart the web service’s web application. I have been monitoring the log for about a month and have NEVER seen the recycle request. To date the code has created over 200 new Active Directory, MOSS, Exchange, and OCS accounts on our system.

Advertisements

2 comments

  1. Hi All,
    We are able to create new user successfully on the active directory but the SetPassword method is taking around 1.5 minutes to complete the process. Below is the code of the snippet of SetPassword. Is there any better approach to set the password of new user?
    #region SetPassword
    ///
    /// This function is used to set user password
    ///
    ///
    ///
    ///

    ///
    internal static void SetPassword(string path, string userPassword)
    {
    if (_logger.IsDebugEnabled)
    _logger.Debug(“ADHelper.cs : Enter SetPassword”);

    try
    {
    using (DirectoryEntry usr = GetDirectoryEntry(path))
    {
    object ret = usr.Invoke(“SetPassword”, userPassword);
    usr.CommitChanges();
    usr.Close();
    }

    if (_logger.IsDebugEnabled)
    _logger.Debug(“ADHelper.cs : Exit SetPassword”);
    }
    catch (Exception ex)
    {
    if (_logger.IsErrorEnabled)
    _logger.Error(“ADHelper.cs : Exception occurred in SetPassword. Message: “, ex);

    throw ex;
    }
    }

    #endregion
    Here is our production environment type.
    • IIS 7
    • ASP.NET 3.5 (C#)
    • Active Directory
    • Windows Server 2008 R2

    Add user snippet
    #region AddUser

    ///
    /// This function is used to add user to active directory
    ///
    /// Active Directory
    /// directory entry object
    ///
    ///
    public static void AddUser(ADUser adUser)
    {
    if (_logger.IsDebugEnabled)
    _logger.Debug(“ADHelper.cs : Enter AddUser”);

    // Local variables
    DirectoryEntry oDE = null;
    DirectoryEntry oDENewUser = null;
    DirectoryEntries oDEs = null;

    try
    {
    oDE = GetDirectoryEntry(GetADPath(Constants.EnvironmentType.PROD, adUser.UserType));

    // 1. Create user account
    oDEs = oDE.Children;
    oDENewUser = oDEs.Add(string.Format(“{0}=”, Constants.ADAttributes.CN) + adUser.UserName, “user”);

    // 2. Set properties
    SetProperty(oDENewUser, Constants.ADAttributes.givenName, adUser.FirstName);
    SetProperty(oDENewUser, Constants.ADAttributes.sn, adUser.LastName);
    SetProperty(oDENewUser, Constants.ADAttributes.mail, adUser.Email);
    SetProperty(oDENewUser, Constants.ADAttributes.sAMAccountName, adUser.UserName);
    oDENewUser.CommitChanges();

    // 3. Set password
    SetPassword(oDENewUser.Path, adUser.Password);

    // 4. Enable account
    EnableAccount(oDENewUser);

    oDENewUser.Close();
    oDE.Close();

    if (_logger.IsDebugEnabled)
    _logger.Debug(“ADHelper.cs : Exit AddUser”);
    }
    catch (Exception ex)
    {
    if (_logger.IsErrorEnabled)
    _logger.Error(“ADHelper.cs : Exception occurred in AddUser. Message: “, ex);

    throw ex;
    }
    finally
    {
    if (oDENewUser != null)
    {
    oDENewUser.Dispose();
    oDENewUser = null;
    }

    if (oDEs != null)
    {
    oDEs = null;
    }

    if (oDE != null)
    {
    oDE.Dispose();
    oDE = null;
    }
    }
    }

    #endregion

    THANKS IN ADVANCE!!!

    1. We had code similar to this for our system at the time but it was resulting in errors every now and then. Our System was using Windows Server 2003 R2 as the domain controller. In our conversations with Microsoft they said the issue was resolved in Server 2008, but the hot fix was not going to be available for Server 2003.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s