Everything in Active Directory via C#.Net 3.5 (Using System.DirectoryServices.AccountManagement)

By | June 28, 2010

Before .Net managing Active Directory objects is a bit lengthy and you need a good knowledge on the principal store to have your head around on what you want to do.  We ususally use the System.DirectoryServices namespace but with .Net 3.5 they introduced System.DirectoryServices.AccountManagement which is manages directory objects independent of the System.DirectoryServices namespace.

So what are the advantages of using this if I have already a library created for the whole AD Methods that System.DirectoryServices exposed?  Because everything is really simple in terms of managing a user, computer or group principal and performing queries on the stores are much faster thanks to the Fast Concurrent Bind (FSB) feature which caches the connection which decreases the number of ports used in the process.

I remember I had posted a while back Active Directory Objects and C# which is basically everything regarding AD Methods in terms of Users and Group management and if you see the codebase is a bit lengthy and you need a bit of understanding on setting and getting hex values thats why I ennumerated it.  Now I had rewritten it using the System.DirectoryServices.AccountManagement namespace, fucntionalities remain the same but its easier to understand and there are fewer lines.|

The code is divided into several regions but here are the 5 key regions with their methods explained

Validate Methods

  • ValidateCredentials – This Method will validate the users credentials.
  • IsUserExpired – Checks if the User Account is Expired.
  • IsUserExisiting – Checks if user exsists on AD.
  • IsAccountLocked  – Checks if user account is locked

Search Methods

  • GetUser – This will return a UserPrincipal Object if the User Exists

User Account Methods

  • SetUserPassword – This Method will set the Users Password
  • EnableUserAccount – This Method will Enable a User Account
  • DisableUserAccount – This Methoid will Disable the User Account
  • ExpireUserPassword – This Method will Force Expire a Users Password
  • UnlockUserAccount – This Method will unlocks a User Account
  • CreateNewUser – This Method will Create a new User Directory Object
  • DeleteUser – This Method will Delete an AD User based on Username.

Group Methods

  • CreateNewGroup – This Method will create a New Active Directory Group
  • AddUserToGroup – This Method will add a User to a group
  • RemoveUserFromGroup – This Method will remove a User from a Group
  • IsUserGroupMember – This Method will Validate whether the User is a Memeber of a Group
  • GetUserGroups – This Method will return an ArrayList of a User Group Memberships

Helper Methods

  • GetPrincipalContext – Gets the base principal context

Now here are the codes

using System;
using System.Collections;
using System.Text;
using System.DirectoryServices.AccountManagement;
using System.Data;
using System.Configuration;

public class ADMethodsAccountManagement
{

#region Variables

private string sDomain = "test.com";
private string sDefaultOU = "OU=Test Users,OU=Test,DC=test,DC=com";
private string sDefaultRootOU = "DC=test,DC=com";
private string sServiceUser = @"ServiceUser";
private string sServicePassword = "ServicePassword";

#endregion
#region Validate Methods

/// <summary>
/// Validates the username and password of a given user
/// </summary>
/// <param name="sUserName">The username to validate</param>
/// <param name="sPassword">The password of the username to validate</param>
/// <returns>Returns True of user is valid</returns>
public bool ValidateCredentials(string sUserName, string sPassword)
{
    PrincipalContext oPrincipalContext = GetPrincipalContext();
    return oPrincipalContext.ValidateCredentials(sUserName, sPassword);

}

/// <summary>
/// Checks if the User Account is Expired
/// </summary>
/// <param name="sUserName">The username to check</param>
/// <returns>Returns true if Expired</returns>
public bool IsUserExpired(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    if (oUserPrincipal.AccountExpirationDate != null)
    {
        return false;
    }
    else
    {
        return true;
    }
}

/// <summary>
/// Checks if user exsists on AD
/// </summary>
/// <param name="sUserName">The username to check</param>
/// <returns>Returns true if username Exists</returns>
public bool IsUserExisiting(string sUserName)
{
    if (GetUser(sUserName) == null)
    {
        return false;
    }
    else
    {
        return true;
    }
}

/// <summary>
/// Checks if user accoung is locked
/// </summary>
/// <param name="sUserName">The username to check</param>
/// <returns>Retruns true of Account is locked</returns>
public bool IsAccountLocked(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    return oUserPrincipal.IsAccountLockedOut();
}
#endregion

#region Search Methods

/// <summary>
/// Gets a certain user on Active Directory
/// </summary>
/// <param name="sUserName">The username to get</param>
/// <returns>Returns the UserPrincipal Object</returns>
public UserPrincipal GetUser(string sUserName)
{
    PrincipalContext oPrincipalContext = GetPrincipalContext();

    UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
    return oUserPrincipal;
}

/// <summary>
/// Gets a certain group on Active Directory
/// </summary>
/// <param name="sGroupName">The group to get</param>
/// <returns>Returns the GroupPrincipal Object</returns>
public GroupPrincipal GetGroup(string sGroupName)
{
    PrincipalContext oPrincipalContext = GetPrincipalContext();

    GroupPrincipal oGroupPrincipal = GroupPrincipal.FindByIdentity(oPrincipalContext, sGroupName);
    return oGroupPrincipal;
}

#endregion

#region User Account Methods

/// <summary>
/// Sets the user password
/// </summary>
/// <param name="sUserName">The username to set</param>
/// <param name="sNewPassword">The new password to use</param>
/// <param name="sMessage">Any output messages</param>
public void SetUserPassword(string sUserName, string sNewPassword, out string sMessage)
{
    try
    {
        UserPrincipal oUserPrincipal = GetUser(sUserName);
        oUserPrincipal.SetPassword(sNewPassword);
        sMessage = "";
    }
    catch (Exception ex)
    {
        sMessage = ex.Message;
    }

}

/// <summary>
/// Enables a disabled user account
/// </summary>
/// <param name="sUserName">The username to enable</param>
public void EnableUserAccount(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    oUserPrincipal.Enabled = true;
    oUserPrincipal.Save();
}

/// <summary>
/// Force disbaling of a user account
/// </summary>
/// <param name="sUserName">The username to disable</param>
public void DisableUserAccount(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    oUserPrincipal.Enabled = false;
    oUserPrincipal.Save();
}

/// <summary>
/// Force expire password of a user
/// </summary>
/// <param name="sUserName">The username to expire the password</param>
public void ExpireUserPassword(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    oUserPrincipal.ExpirePasswordNow();
    oUserPrincipal.Save();

}

/// <summary>
/// Unlocks a locked user account
/// </summary>
/// <param name="sUserName">The username to unlock</param>
public void UnlockUserAccount(string sUserName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    oUserPrincipal.UnlockAccount();
    oUserPrincipal.Save();
}

/// <summary>
/// Creates a new user on Active Directory
/// </summary>
/// <param name="sOU">The OU location you want to save your user</param>
/// <param name="sUserName">The username of the new user</param>
/// <param name="sPassword">The password of the new user</param>
/// <param name="sGivenName">The given name of the new user</param>
/// <param name="sSurname">The surname of the new user</param>
/// <returns>returns the UserPrincipal object</returns>
public UserPrincipal CreateNewUser(string sOU, string sUserName, string sPassword, string sGivenName, string sSurname)
{
    if (!IsUserExisiting(sUserName))
    {
        PrincipalContext oPrincipalContext = GetPrincipalContext(sOU);

        UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext, sUserName, sPassword, true /*Enabled or not*/);

        //User Log on Name
        oUserPrincipal.UserPrincipalName = sUserName;
        oUserPrincipal.GivenName = sGivenName;
        oUserPrincipal.Surname = sSurname;
        oUserPrincipal.Save();

        return oUserPrincipal;
    }
    else
    {
        return GetUser(sUserName);
    }
}

/// <summary>
/// Deletes a user in Active Directory
/// </summary>
/// <param name="sUserName">The username you want to delete</param>
/// <returns>Returns true if successfully deleted</returns>
public bool DeleteUser(string sUserName)
{
    try
    {
        UserPrincipal oUserPrincipal = GetUser(sUserName);

        oUserPrincipal.Delete();
        return true;
    }
    catch
    {
        return false;
    }
}

#endregion

#region Group Methods

/// <summary>
/// Creates a new group in Active Directory
/// </summary>
/// <param name="sOU">The OU location you want to save your new Group</param>
/// <param name="sGroupName">The name of the new group</param>
/// <param name="sDescription">The description of the new group</param>
/// <param name="oGroupScope">The scope of the new group</param>
/// <param name="bSecurityGroup">True is you want this group to be a security group, false if you want this as a distribution group</param>
/// <returns>Retruns the GroupPrincipal object</returns>
public GroupPrincipal CreateNewGroup(string sOU, string sGroupName, string sDescription, GroupScope oGroupScope, bool bSecurityGroup)
{
    PrincipalContext oPrincipalContext = GetPrincipalContext(sOU);

    GroupPrincipal oGroupPrincipal = new GroupPrincipal(oPrincipalContext, sGroupName);
    oGroupPrincipal.Description = sDescription;
    oGroupPrincipal.GroupScope = oGroupScope;
    oGroupPrincipal.IsSecurityGroup = bSecurityGroup;
    oGroupPrincipal.Save();

    return oGroupPrincipal;
}

/// <summary>
/// Adds the user for a given group
/// </summary>
/// <param name="sUserName">The user you want to add to a group</param>
/// <param name="sGroupName">The group you want the user to be added in</param>
/// <returns>Returns true if successful</returns>
public bool AddUserToGroup(string sUserName, string sGroupName)
{
    try
    {
        UserPrincipal oUserPrincipal = GetUser(sUserName);
        GroupPrincipal oGroupPrincipal = GetGroup(sGroupName);
        if (oUserPrincipal != null && oGroupPrincipal != null)
        {
            if (!IsUserGroupMember(sUserName, sGroupName))
            {
                oGroupPrincipal.Members.Add(oUserPrincipal);
                oGroupPrincipal.Save();
            }
        }
        return true;
    }
    catch
    {
        return false;
    }
}

/// <summary>
/// Removes user from a given group
/// </summary>
/// <param name="sUserName">The user you want to remove from a group</param>
/// <param name="sGroupName">The group you want the user to be removed from</param>
/// <returns>Returns true if successful</returns>
public bool RemoveUserFromGroup(string sUserName, string sGroupName)
{
    try
    {
        UserPrincipal oUserPrincipal = GetUser(sUserName);
        GroupPrincipal oGroupPrincipal = GetGroup(sGroupName);
        if (oUserPrincipal != null && oGroupPrincipal != null)
        {
            if (IsUserGroupMember(sUserName, sGroupName))
            {
                oGroupPrincipal.Members.Remove(oUserPrincipal);
                oGroupPrincipal.Save();
            }
        }
        return true;
    }
    catch
    {
        return false;
    }
}

/// <summary>
/// Checks if user is a member of a given group
/// </summary>
/// <param name="sUserName">The user you want to validate</param>
/// <param name="sGroupName">The group you want to check the membership of the user</param>
/// <returns>Returns true if user is a group member</returns>
public bool IsUserGroupMember(string sUserName, string sGroupName)
{
    UserPrincipal oUserPrincipal = GetUser(sUserName);
    GroupPrincipal oGroupPrincipal = GetGroup(sGroupName);

    if (oUserPrincipal != null && oGroupPrincipal != null)
    {
        return oGroupPrincipal.Members.Contains(oUserPrincipal);
    }
    else
    {
        return false;
    }
}

/// <summary>
/// Gets a list of the users group memberships
/// </summary>
/// <param name="sUserName">The user you want to get the group memberships</param>
/// <returns>Returns an arraylist of group memberships</returns>
public ArrayList GetUserGroups(string sUserName)
{
    ArrayList myItems = new ArrayList();
    UserPrincipal oUserPrincipal = GetUser(sUserName);

    PrincipalSearchResult<Principal> oPrincipalSearchResult = oUserPrincipal.GetGroups();

    foreach (Principal oResult in oPrincipalSearchResult)
    {
        myItems.Add(oResult.Name);
    }
    return myItems;
}

/// <summary>
/// Gets a list of the users authorization groups
/// </summary>
/// <param name="sUserName">The user you want to get authorization groups</param>
/// <returns>Returns an arraylist of group authorization memberships</returns>
public ArrayList GetUserAuthorizationGroups(string sUserName)
{
    ArrayList myItems = new ArrayList();
    UserPrincipal oUserPrincipal = GetUser(sUserName);

    PrincipalSearchResult<Principal> oPrincipalSearchResult = oUserPrincipal.GetAuthorizationGroups();

    foreach (Principal oResult in oPrincipalSearchResult)
    {
        myItems.Add(oResult.Name);
    }
    return myItems;
}

#endregion

#region Helper Methods

/// <summary>
/// Gets the base principal context
/// </summary>
/// <returns>Retruns the PrincipalContext object</returns>
public PrincipalContext GetPrincipalContext()
{
    PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword);
    return oPrincipalContext;
}

/// <summary>
/// Gets the principal context on specified OU
/// </summary>
/// <param name="sOU">The OU you want your Principal Context to run on</param>
/// <returns>Retruns the PrincipalContext object</returns>
public PrincipalContext GetPrincipalContext(string sOU)
{
    PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword);
    return oPrincipalContext;
}

#endregion

}

Now this is how to use it.

ADMethodsAccountManagement ADMethods = new ADMethodsAccountManagement();

UserPrincipal myUser = ADMethods.GetUser("Test");
myUser.GivenName = "Given Name";
myUser.Surname = "Surname";
myUser.MiddleName = "Middle Name";
myUser.EmailAddress = "Email Address";
myUser.EmployeeId = "Employee ID";
myUser.Save();
Recommended

143 thoughts on “Everything in Active Directory via C#.Net 3.5 (Using System.DirectoryServices.AccountManagement)

  1. CK

    Great info!
    One question, could you show a nice example of editing an existing user?

    Reply
    1. rsmacaalay

      If you have noticed there is no more attribute editing function on the library I created as it is now exposed on the UserPrincipal namespace itself so if you want to update information such as name, last name, employee id as some samples you can do it by searching for the user like this

      ADMethodsAccountManagement ADMethods = new ADMethodsAccountManagement();

      UserPrincipal myUser = ADMethods.GetUser("your Username");

      and assigning values to it like such:

      myUser.GivenName = "Given Name";
      myUser.Surname = "Surname";
      myUser.MiddleName = "Middle Name";
      myUser.EmailAddress = "Email Address";
      myUser.EmployeeId = "Employee ID";
      myUser.Save();

      Reply
    2. simi

      using this code i am able to create new user but with blank password, code is creating user with blank password.
      Also i need to create user with Admin privilages (should be memebr of Administrator).

      Please reply…….

      Reply
  2. Craig

    Do you have an example of using any of the other methods like removing user from a group, adding user to a group.

    Reply
    1. rsmacaalay

      You can use this two methods RemoveUserFromGroup and AddUserToGroup, the parameters are only User Name and Group Name, if it doesnt find any it returns a boolean variable.

      Reply
  3. Pingback: Active Directory Objects and C# « Raymund Macaalay's Dev Blog

  4. Kishor

    I am trying to hook up with Active directory to get the Group of the user using System.DirectoryServices.AccountManagement.
    When I am running the Application from VS2010 it Authenticate user and Display the Group as well.
    But when I am browsing application from IIS 5.1 it showing error while checking the group.
    “System.DirectoryServices.DirectoryServicesCOMException: Logon failure: unknown user name or bad password.”

    PrincipalContext pc = new PrincipalContext(ContextType.Domain, “TEST1”)
    On Sentence
    UserPrincipal.FindByIdentity(pc, userName);

    Kindly provide some help.

    Reply
      1. Kishor

        hi,

        Please find the code of GetPrincipalContect as given below.

        public PrincipalContext GetPrincipalContext()
        {

        //PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword);
        PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, “TEST1”);
        return oPrincipalContext;
        }

        Reply
    1. rsmacaalay

      Looks like you are using PrincipalContext(ContextType, String) where the or your “TEST1” will be the name of the domain or server hosting the ApplicationDirectory instance. Which means the application will set the default username and password when the instance of the Principal Cotnext initializes, this will be fine on your machine as it will inherit your user who is logged in to the machine but when using IIS if you are not using Integrated Windows Authentication with the Anonymous Access off then it would use the IUSR_SERVERNAME account to initiallize the Principal Cotnext, but if you are using the the Integrated Windows Authentication with the Anonymous Access off can you do a Response.Write of the username the site is running as.

      Reply
      1. Kishor

        Hi,

        I tried to get the username by WindowsIdentity.GetCurrent().Name.ToString()

        When I am browsing application from IIS ( Integrated Windows Authentication with the Anonymous Access off )

        and try to get the user name it showing “PC_NAMEASPNET”

        and

        When I am running from VS2010 it showing “DOMAINMyUserId”
        who is logged in to the machine.

        Reply
      2. Kishor

        Hi this has been resolved.

        When code runs localy using VS2010 it run under my conditionals (user Logon on PC)

        And when it runs from IIS it runs under a small right account.

        So I tried impersonate tag in Web.Config with username and password

        And it worked proper.

        Thanks You very Mush rsmacaalay for your suggession.

        Reply
  5. Pingback: How to use AD Attributes not represented in UserPrincipal, GroupPrincipal and ComputerPrincipal « Raymund Macaalay's Dev Blog

    1. rsmacaalay

      Its simple to use all you need is an AD UserName and AD GroupName so for example you have a username “raymund” and group name “administrators” then the usage is RemoveUserFromGroup(“raymund”, “administrators”), hope this clarifies your question.

      Reply
  6. Dave Reid

    Great stuff! I think the logic on some of the group methods is backwards though. For example, I would think IsUserGroupMember should be like this:

    if (oUserPrincipal == null || oGroupPrincipal == null)
    {
    return false;
    }
    else
    {
    return oGroupPrincipal.Members.Contains(oUserPrincipal);
    }

    so that if either the user or the group is not found, the method returns false.

    Reply
    1. rsmacaalay

      Thanks for pointing that out, I noticed that as well in my codes before but forgot to change my blog post.

      Updating it now so all with || are now using != and && i.e

      if (oUserPrincipal != null && oGroupPrincipal != null)
      {
          return oGroupPrincipal.Members.Contains(oUserPrincipal);
      }
      else
      {
          return false;
      }
      Reply
  7. David

    Hi.
    I’m trying to use your code, but
    At: AddUserToGroup, at line: oGroupPrincipal.Members.Add(oUserPrincipal);

    I Keep getting this exception: System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).

    Do you have a solution?

    Reply
    1. rsmacaalay

      That error means that the “The specified domain either does not exist or could not be contacted.” So the best thing to do first is add the IP address of domain controller that you are using on the DNS server list on the machine the code is running on and make sure thats the first on the list, after doing that do an ipconfig /flushdns

      Here is where you add it

      Reply
      1. David

        THanks, Problem solved. But is there another alternative?
        I don’t know if in production environment I’ll be able to do this.

        Reply
      2. David

        Ops! Not solved, I thought it was, but forgot to change the code to the original one =/
        I ‘Solved’ this using old DirectoryEntry, but I wish to use AccManagement namespace =/

        Reply
      1. Punkster812

        Actually, you should probably look at using the overload if you are connecting that takes the PrincipalContext. This helps the GetGroups even without the DNS server being the first in the list, or even if the computer doesn’t belong to the same Active Directory.

        Reply
  8. Ferdinando

    Could you show an example of how to update for example the department field and office field using this?

    Reply
  9. Timur

    Hi. It’s very useful class but I can’t use this , because I showing error Logon failure: unknown user name or bad password. I want add user to AD in Windows 2003 server. I saw that Kishor resolved this problem but i can’t understend how he did this. Please help me 🙁

    P.S. Sorry for my english.This is not very well, but i try learn this 🙂

    Reply
    1. rsmacaalay

      Can you let me know how your environment work first? Where is your code running? Whats calling it? etc. Then I guess we can start from there.

      Reply
      1. Timur

        OK , I try use for create new user in domain
        UserPrincipal myNewUser = ADMethods.CreateNewUser("test.com", tbLogin.Text.Trim(), tbPassword.Text.Trim(),
        "Name", "Simple name", "Simple surname", "893456463", "dfsg@sibmail.com");
        myNewUser.Save();

        and i showing message “the user name or password unidentified” .I lunch application on the server machine

        Reply
  10. Timur

    tbLogin is textbox.text = “login”;
    tbPassword is textbox.tex = “password”;

    Reply
      1. Timur

        private string sDomain = “test.com”;
        private string sDefaultOU = “OU=Users,OU=Test,DC=test,DC=com”;
        private string sDefaultRootOU = “DC=test,DC=com”;
        private string sServiceUser = @”Администратор”;
        private string sServicePassword = “12345”;

        Reply
  11. Abe

    I have a user in one domain – say domain A. This user is a member of a few groups in Domain A and a few groups in Domain B. The GetUserGroups function will only return the groups in Domain A. How can I get the groups for Domain B as well? Any help is greatly appreciated.

    Reply
    1. rsmacaalay

      You need to connect in two different PrincipalContexts which you can programatically assign in the PrincipalContext method. This means you execute User.GetGroups(PrincipalContext) in two different PrincipalContexts and merge the results.

      Reply
  12. Pingback: Synchronizing Google Groups and Active Directory Group Members « Raymund Macaalay's Dev Blog

  13. Christos K

    Nice and thank you very much!!. I’ve failed to see the use of the variable : sDefaultRootOU

    Reply
  14. khairil anwar

    Hi,

    Firstly thank to teach us here. Really appreaciate what you have done. Yup, your blog is one of must see for me :).

    I cannot help myself keep wondering on this article about 3 things:

    1. My domain have deep OU level – more than 3. Let say, I have OU “Deparments” right under root, then OU “” and OU “”. Such it become contoso.edu->Departments->ComputerScience->2011. Can the GetPrincipalContext() be able to validate user just only by given root OU?

    2. My domain also have other 5 sub domains, with all the domains are GCs. Can I do search/validate user just by giving the root domain with UserName complete with domain, such validate “khairil@student.contoso.edu from root domain “contoso.edu”?

    3. I have Forest level trust relation with other forest, fictionally named “fabrikam.com”. Can I validate their user using your code? What are modification that I need to do?

    Sorry, asking you to many questions, I just new comer to AD. Anyway, thank you very much for your articles.

    -khairil-

    Reply
    1. rsmacaalay

      Hi kharil,

      1. sDefaultOU and anything below it would be the scope of any queries or actions you do in Active Directory. So the answer on your question is yes, regardless how deep your OU is as long as it belong to the root then it will be fine. But please note that sDefaultRootOU was not used in the above code, it was my mistake.
      2. You have to change sub domains by changing sDomain and sDefaultOU. And sub domains will be treated as a different repository thats why in Windows Login you are asked the option of which domain to log in to as it will not search your user credentials in other sub domains.
      3. Like in item 2 you need to be specific to a domain.

      I hope i understood your questions and answered them 🙂

      Reply
      1. khairil anwar

        Hi Raymund,

        Thanks for the tips, 🙂 yup that answered my questions.

        At first I thought, when a domain is GC I do not have to specify a domian, just giving UserName with full user@domain combination. You have clear it up for me.

        Just another question, do “sServiceUser” need to be a special account like domain admin or enterprise admin,or just any normal account will do?

        Thank you very much for the answer. Happy weekend then.

        -Khairil-

        Reply
  15. Dave

    Greetings,

    Have you noticed any problems with caching? I have a project where I used these AccountManagement principals and I can’t seem to figure out how to refresh the cache. Removing items from a group is particularly visible. It takes a variable amount of time before removed items are gone which I would presume is the normal interval that the cache is flushed. groupPrincipal,Save() does not flush the local cache apparently.

    Your thoughts are appreciated.

    Reply
    1. rsmacaalay

      Do you have multiple Domain Controllers? If you have, that might be the case as it need to synchronize between different controllers and te time depends on the amount of data being synchronized between the two. To actually confrim this you need to view items directly on the Domain Controller your application is connected to via the Active Directory Users and computers

      Reply
  16. panindra nadig

    Hi, I am new to active directory , I have a task where i will be having user names and i nedd to fing corresponding group and ou related and second I need to move user from one group to another. How can I achive this I tried all near possibalities given in posts on internet.Hope you will reply soon for my query.

    Thanks
    Panindra Nadig

    Reply
    1. rsmacaalay

      What do you mean by “i nedd to fing corresponding group and ou related”? also OU you can move but groups you can join an unjoin those are two different things. So for the groups you can use the AddUserToGroup and RemoveIuserFromGroup methods

      Reply
  17. Vincent

    Hey thanks for the code, looks like its working pretty great in VS2010 with running credentials but I cant get it work running under supplied credentials on the IIS server by enabling anonymous mode. I am fairly new to this but how could i run everything under the credentials in IIS and not a plain text file.

    Reply
    1. rsmacaalay

      Not a good idea to run it in anonymous mode, you either need to run it with IIS Credentials that have very defined security roles or you can do Windows authentication and let the users credentials define what methods he have access to run.

      Reply
  18. Thomas

    How would I get a list of users and their managers using your code?

    Reply
    1. Thomas

      Managed to create the method in the meantime

      public struct ADUser
      {
      public String Name;
      public String Surname;
      public String AccountName;
      public String PrincipleName;
      }

      public ArrayList GetUserList()
      {
      PrincipalContext oPrincipalContext = GetPrincipalContext(sDefaultOU);

      ArrayList Results = new ArrayList();

      using (var searcher = new PrincipalSearcher(new UserPrincipal(oPrincipalContext)))
      {
      foreach (var result in searcher.FindAll())
      {
      ADUser LoadUser;

      DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;

      LoadUser.Name = de.Properties[“givenName”].Value.ToString();
      LoadUser.Surname = de.Properties[“givenName”].Value.ToString();
      LoadUser.AccountName = de.Properties[“givenName”].Value.ToString();
      LoadUser.PrincipleName = de.Properties[“givenName”].Value.ToString();

      Results.Add(LoadUser);
      }
      }

      return Results;
      }

      Reply
    2. rsmacaalay

      Sorry for the late reply was in TechEd last week anyways better late than never.

      For your question, Here is a sample on how you get a list of users returning as
      an ArrayList

      public ArrayList GetUsers(string sSearchString, string sSearchColumn)
      {
          ArrayList myItems = new ArrayList();
          PrincipalSearcher oPrincipalSearcher = new PrincipalSearcher();
          UserPrincipal oUserPrincipal = new UserPrincipal(GetPrincipalContext());
          switch (sSearchColumn)
          {
              case "Name":
                  oUserPrincipal.Name = "*" + sSearchString + "*";
                  break;
              case "GivenName":
                  oUserPrincipal.GivenName = "*" + sSearchString + "*";
                  break;
              case "Surname":
                  oUserPrincipal.Surname = "*" + sSearchString + "*";
                  break;
              case "SamAccountName":
                  oUserPrincipal.SamAccountName = "*" + sSearchString + "*";
                  break;
              default:
                  oUserPrincipal.DisplayName = "*" + sSearchString + "*";
                  break;
          }
       
          oPrincipalSearcher.QueryFilter = oUserPrincipal;
       
          PrincipalSearchResult<Principal> oPrincipalSearchResults = oPrincipalSearcher.FindAll();
          foreach (Principal p in oPrincipalSearchResults)
          {
              myItems.Add((UserPrincipal)p);
          }
          return myItems;
      }

      and to get the users manager here is the method

      public static UserPrincipal GetUserManager(string sUserName)
      {
          UserPrincipal oUserManager = null;
          UserPrincipal oUser = ActiveDirectory.GetUser(sUserName);
          if (oUser != null)
          {
              string sManagerDistinguishedName = oUser.GetProperty("manager");
              if (!string.IsNullOrEmpty(sManagerDistinguishedName))
              {
                  oUserManager = ActiveDirectory.GetPrincipalByDistinguishedName(sManagerDistinguishedName) as UserPrincipal;
              }
          }
       
          return oUserManager;
      }    

       

      Reply
  19. raj

    when i am validating username and password by
    PrincipalContext oPrincipalContext = GetPrincipalContext();
    return oPrincipalContext.ValidateCredentials(sUserName, sPassword);
    this function it gives always return false but username and password is correct

    Reply
    1. Christian MA

      using System;
      using System.DirectoryServices;

      public class RenameObject
      {
      public static void Main()
      {
      DirectoryEntry de = new DirectoryEntry(
      “LDAP://192.168.1.100/ou=auditing, ou=accounting, dc=ispnet1, dc=net”,
      “cn=Administrator, dc=ispnet1, dc=net”, “password”,
      AuthenticationTypes.ServerBind);

      DirectoryEntries des = de.Children;
      DirectoryEntry badObject = des.Find(“cn=test”);
      badObject.Rename(“cn=testing”);
      de.CommitChanges();
      de.Close();
      }
      }

      Reply
  20. Peter

    Hello, ¿can i rename group of users with GroupPrincipal?

    GroupPrincipal gp=GetGroup(“TEST”);
    gp.name=”NEW NAME”;
    gp.save(); //ERROR not possible change RDN !

    Any ideas? Very thank you

    Reply
    1. rsmacaalay

      RDN or Relative Distinguished Name is like a primary key on the database so you cant rename that, what you can do is change the display name but if you really want to change the name you need to drop and recreate it programatically, I guess thats what happens when you use the Active Directory Users and Computers, it just looks like you are renaming it.

      Reply
    2. Christian MA

      using System;
      using System.DirectoryServices;

      public class RenameObject
      {
      public static void Main()
      {
      DirectoryEntry de = new DirectoryEntry(
      “LDAP://192.168.1.100/ou=auditing, ou=accounting, dc=ispnet1, dc=net”,
      “cn=Administrator, dc=ispnet1, dc=net”, “password”,
      AuthenticationTypes.ServerBind);

      DirectoryEntries des = de.Children;
      DirectoryEntry badObject = des.Find(“cn=test”);
      badObject.Rename(“cn=testing”);
      de.CommitChanges();
      de.Close();
      }
      }

      Reply
  21. Zinzow

    Thank you, I have recently been looking for details about this subject matter for ages and yours is the best I have found so far.

    Reply
  22. Peter

    I am hoping I can get some help here. How can I copy an AD user in order to create another AD user? For example, I have a template user that I simply want to copy and create a new user JSmith. JSmith is now EXACTLY like the template user except of course for uniquely needed fields such as username and such. Is this possible? Please assist.

    Reply
    1. Thomas

      @Peter: I would set a specific user ( so create a user or use an existing one) as the template and create a function to fetch all of the details of that user, leaving out certain details like the email address, name, surname etc that would be unique for the new user to be created. Then use the functionality to create a new user using those details. If this is a constant function that you would be using, I would suggest that you generate an xml file with the details and just read the file instead of hammering the AD

      Reply
      1. Peter

        But would this copy everything from the original user? All groups and rights and settings, etc.?

        Reply
    2. rsmacaalay

      Hi Peter, while its not a good practice to copy ones credentials it will be possible but like what Thomas said you need to create a template and thats the best practice. That template can be on XML or in SQL where it defines a specific definition for the user that you will be creating.

      Also on your question regarding the file and folder permissions well if the file or folder was granted permission because of an AD group then it would be easy but if its granted by the username then good luck as you dont have any reference from AD what files have been granted unless you iterate to all of the files and folders and check the permissions. Hope this helps.

      Reply
  23. Sandra Diehl

    This is great and very helpful with the application I have been creating. Right now I need the ability to create and delete computers in Active Directory. I have been able to do it using the more combersome method, but I like the cleaniness of this method you have display so well. Would you happen to have example of both methods?

    One thing that I found while attempting to create the computer that it wasn’t getting placed into the correct account type and had to set the userAccountControl to 4128 in order for it to get enabled and set up so it could attached to the domain…also had to set the PrimaryGroupID to 515…need something clean

    Reply
  24. Sandra Diehl

    Oh and another Active Directory task that I like to be able to do in my application is the ability to rename a user to change the following properties: Full Name (cn), First Name (givenName), Last Name (sn), Display Name (displayName) and the User logon – we have a special formatting rule for the user logon id so I would have to create a new logon based on that rule and then set the userPrincipalName and SAMAccountName with the new value.

    Reply
  25. Pingback: how do i create new OU in Active Directory using DirectoryServices.AccountManagement in .net 3.5 or 4 | trouble86.com

    1. rsmacaalay

      The answer given in StackOver Flow is correct there is no way in .Net 3.5 you can manage Organizational Units so you have to use the DirectoryEntry Object in the System.DirectoryServices.ActiveDirectory namespace so here is a mehod just to achieve what you want

      public void CreateNewOU(string sOU, string sNewOU, string sOUDescription)
      {
      string sLDAPPath = "LDAP://" + sDomain + "/" + sOU;
      DirectoryEntry oParentOU = new DirectoryEntry(sLDAPPath);
      DirectorySearcher oDirectorySearcher = new DirectorySearcher(oParentOU);
      oDirectorySearcher.Filter = "(" + sNewOU + ")";
      oDirectorySearcher.SearchScope = SearchScope.Subtree;
      SearchResult oSearchResult = oDirectorySearcher.FindOne();
      if (oSearchResult == null)
      {
      DirectoryEntry oNewOU = oParentOU.Children.Add(sNewOU, "OrganizationalUnit");
      oNewOU.Properties["description"].Add(sOUDescription);
      oNewOU.CommitChanges();
      }
      }

      usage

      ADMethodsAccountManagement myAD = new ADMethodsAccountManagement();
      myAD.CreateNewOU("OU=Parent OU,DC=com,DC=test", "OU=New OU", "Test Organizational Unit Description");

      Reply
  26. Chris W

    I am using the GetUser method as described above. When I execute the FindByIdentity method, I get an exception with “A referral was returned from the server”. I’m a newbie in terms of AD, so I’m not sure what this means.

    I’m using the following connection string. This was the only way I could get past “Unable to connect to server” and “Invalid Login/Password” messages.

    PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, “MyDomain.local”, “dc=domain,dc=com”, ContextOptions.SimpleBind, “MyDomain\” + sServiceUser, sServicePassword);

    Reply
    1. rsmacaalay

      Can you give me your full codes where form your connection to the method you are using, as well as your full exception so that I can debug it.

      Reply
      1. Chris W

        I think I have it figured out. When I specify MyDomain.local as the domain name, I then need to specify “dc=MyDomain,dc=local”. Before I had “com” instead of “local”.

        Thanks for the response, though.

        Reply
  27. Fred Roines

    Hi,

    Good information ,

    Can you please show a code to get all members of a group?

    thank you in advance
    Fred

    Reply
    1. rsmacaalay

      Usng the GetGroup Method above then the code below

       
      public PrincipalCollection GetGroupMembers(string sGroupName)
      {
          GroupPrincipal oGroupPrincipal = GetGroup(sGroupName);
       
          if (oGroupPrincipal != null)
          {
              return oGroupPrincipal.Members;
          }
          else
          {
              return null;
          }
      }
        

      Usage

      foreach (UserPrincipal oUser in GetGroupMembers("YourGroupName"))
      {
          string sUserName = oUser.SamAccountName;
      }

       

      Reply
      1. Fred Roines

        Hi,

        Ok , the range of members groups seems to be 0-1500 …

        how I can get or to know the count of members when it more than 1500+

        thank u in advance
        Fred

        Reply
  28. Fred Roines

    Hi again

    Could you please show a code to get all users under criteria ?

    e.g : I would like to search all users where

    (&(employeeType=employee)(extensionAttribute=*-US))

    thank you in advance
    Fred

    Reply
    1. rsmacaalay

      Since those attributes are not represented in the UserPrincipal object you need to extend it and here is my article regarding that topic http://anyrest.wordpress.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/. Once you had extended the attributes to have employeeType and extensionAttribute you can now use the usual PrincipalSearcher like such with the combination of the library above.

      ArrayList myItems = new ArrayList();
      PrincipalSearcher oPrincipalSearcher = new PrincipalSearcher();
      UserPrincipal oUserPrincipal = new UserPrincipal(GetPrincipalContext());
      oUserPrincipal.EmployeeType = "employee";
      oUserPrincipal.ExtensionAttribute = "*-US";
      oPrincipalSearcher.QueryFilter = oUserPrincipal;
       
      PrincipalSearchResult<Principal> oPrincipalSearchResults = oPrincipalSearcher.FindAll();
      foreach (Principal p in oPrincipalSearchResults)
      {
          myItems.Add((UserPrincipal)p);
      }
      Reply
      1. Mouliin

        Hi Fred, did u solve this extensionAttribute issue ?
        I am trying to provide a role-based access to my intranet system using AD and different web-apps are listed as extensioAttributes.

        so I need to check if Use has perticular app in his/her list or not ? if yes then its OK otherwise they should be redirected to mycompanyhome.company.co.uk

        please post your solution idea.

        Raymund, can you please explain this with some more example

        regards
        Maulin

        Reply
  29. Jim Cooper

    Nice content, but you shouldn’t write code like this:

    if (oUserPrincipal.AccountExpirationDate != null)
    {
    return false;
    }
    else
    {
    return true;
    }

    It’s sufficient, and at least equally as clear, to write:

    return oUserPrincipal.AccountExpirationDate == null;

    Reply
  30. Jonsen

    This is very good & thanks.

    Do you have an example of retrieving all Distribution Groups (Exchange Distribution Lists) from Active Directory?

    Thank you.

    Reply
  31. Jonsen

    Sorry, I need the email address associated with all found Distribution Groups.

    Reply
  32. Jonsen

    Thank you for replying.

    I am not looking to retrieve the members of a group. I need to retreive all email Dustribution Groups (Exchange Dustributions Lists) and their associated email address. I seems that the answer in the link above referes to members of a group.

    Your help is appreciated.

    Reply
    1. rsmacaalay
      /// <summary>
      /// Gets All Groups in Active Directory
      /// </summary>
      /// <param name="sOU">The OU you want to search the groups from</param>
      /// <param name="bSecurityGroup">Use True for Security Groups, and False for Distribution Groups</param>
      /// <returns>An Array List of all Group Principals</returns>
      public ArrayList GetGroups(string sOU, bool bSecurityGroup)
      {
          ArrayList myItems = new ArrayList();
       
          GroupPrincipal oGroupPrincipal = new GroupPrincipal(GetPrincipalContext(sOU));
       
          oGroupPrincipal.IsSecurityGroup = bSecurityGroup;
          PrincipalSearcher mySearch = new PrincipalSearcher(oGroupPrincipal);
          mySearch.QueryFilter = oGroupPrincipal;
       
          PrincipalSearchResult<Principal> oPrincipalSearchResult = mySearch.FindAll();
       
          foreach (GroupPrincipal oResult in oPrincipalSearchResult)
          {
              myItems.Add(oResult);
          }
       
          return myItems;
      }

      And to use it

      foreach (GroupPrincipal oGroupPrincipal in GetGroups("OU=YourOU,DC=com,DC=testing"false))
      {
          string sGroupName = oGroupPrincipal.Name;
          string sEmail = GetProperty(oGroupPrincipal, "mail");
      }

      please note you have to use some of the existing methods above for this to work, also add this one below

      /// <summary>
      /// This will retreive the specified poperty value from the DirectoryEntry object (if the property exists)
      /// </summary>
      /// <param name="oDE"></param>
      /// <param name="sPropertyName"></param>
      /// <returns></returns>
      public string GetProperty(Principal oPrincipal, string sPropertyName)
      {
          DirectoryEntry oDE = (oPrincipal.GetUnderlyingObject() as DirectoryEntry);
       
          if (oDE.Properties.Contains(sPropertyName))
          {
              return oDE.Properties[sPropertyName][0].ToString();
          }
          else
          {
              return string.Empty;
          }
      }
      Reply
      1. Josen

        Hi,
        as mentioned this is working just fne and thanks for your help. Just one furhter point, I have a requirement to return Dynmanic Distribution Groups which are available in Exchange 2007+ environments. Is it possible to retrieve Dynamic Distribution Groups using System.DirectoryServices.AccountManagement or do I need another method? If you could provide

        Reply
  33. Fred Roines

    Hi ,

    Question : when using System.DirectoryServices namespace , you can use .addrange to add multiple members to a group in a single operation, so is it possible by using System.DirectoryServices.AccountManagement

    if yes, could you please show an example? =)

    Thank in advance
    Fred

    Reply
  34. ninad

    hi ,

    i want to set a permission in active directory and user controls at particular OU and all sub OU’S under this OU to authenticated user’s for read permission.i am using console application in c#.please tell me how to implement it using ldap in c#

    Reply
  35. Muhammad Idrees

    That’s are great article, I got some good knowledge. But one thing i need to know (sorry have no idea). what is the real / practical usage of this code. Could you please suggest any example where this trick is helpful.

    Reply
    1. rsmacaalay

      If youre developing some sort of Identity Mangement Solution or even just a user management then this would be a great use.

      Reply
  36. firoz

    Is it possible to get the password of the user.why becoz i am creating reset password webpart in sharepoint fba site.the users can change their passwords.(both fba and ad users).

    Reply
    1. rsmacaalay

      No its not possible, I have the same situation before “creating a password reset as a SP web part” what Ive done is extended AD the schema to have the secret question id and secret question answer (encrypted of course). And to force users to fill this up is when the fire up sharepoint front page I have a web part that intercepts the landing page and checks if they have already set up the secret question if not they will be redirected to a setup page otherwise they continue normally

      Reply
  37. Cosmin

    Excellent piece of work!
    Congratulations for it and a million thanks for saving me of such a big effort!

    Reply
  38. cnadeemahmed

    I am unable to find manager object based on its name property if the user and its manager are in different domain. Lets say top domain is BIG and under that we have subdomain1,2,3 etc. User belong to subdomain1 and manager in subdomain2. Search operation not working on TOP domain.
    Below is my code

    UserPrincipal oUserPrincipal = GetUser();
    PrincipalContext oPrincipalContext = GetPrincipalContext();
    UserPrincipalEx ex = UserPrincipalEx.FindByIdentity(oPrincipalContext, oUserPrincipal.SamAccountName);

    if (sFieldName == ”manager”)
    {
    string strManager = ex.GetUserFieldData(sFieldName);
    if (!string.IsNullOrEmpty(strManager))
    {

    UserPrincipal oManagerPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, strManager);
    return oManagerPrincipal.DisplayName + ”$$$” + oManagerPrincipal.EmailAddress;
    }
    return ””;
    }
    return ex.GetUserFieldData(sFieldName);
    At line UserPrincipal oManagerPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, strManager); oPrincipalContext belong to user who belong to subdomain1 and strmanager is the name of manager which I get from extendedUserPrincipal.

    Plz suggest

    WordPress.com / Gravatar.com credentials can be used.

    Reply
  39. Ammar Bukhari

    This is an excellent article. Its helping me to design an application that will sync users from a DB to AD. Now i am just stuck at a problem, how do i only search for users in the entire AD. if dont know the names of the nodes. I saw in AD that there is a Type that says “USER” but i cant find this in the objects that i have from your code.

    Please help!

    Reply
  40. Shayaan

    I am getting errors on
    ADMethodsAccountManagement — Type or namespace could not be found
    and
    ActiveDirectory — The name ‘ActiveDirectory’ could not be found.

    Here are my namespaces:
    using System;
    using System.Collections;
    using System.Text;
    using System.Windows.Forms;
    using System.DirectoryServices;
    using System.DirectoryServices.AccountManagement;
    using System.Data;
    using System.Configuration;

    Reply
  41. lomire

    Great blog. very helpful, thank you very much.

    My question is indirectly associated with AD. Can you show some code for reads data from the syslog about AD changes and leading them to the same AccountManagment classes ? If you made this code for read/erite AD objects you most likely made and the code for changes monitoring.

    Thank You.

    Reply
  42. Mohammad Danish

    Hi,

    Thanks for providing such a simple and useful methods for handling AD. Everything is working fine except SetUserPassword Method which is not taking into account the Password History Policy of Ad. It is just resetting it to the value we provide. Unlike SetUserPassword, ChangePassword is taking care of all the AD policies. But I can’t use ChangePassword method when user is not having his old password. So in that case I have to use SetUserPassword method.
    Please help to resolve this issue.

    Thanks!

    Reply
    1. rsmacaalay

      That is really how it works as SetUserPassword is meant for Admins similar to reset password in Active Directory Users and Computers while ChangeUserPassword is meant for end users to reset their password meaning they should know their old one

      Reply
      1. Mohammad Danish

        Ok, but I am still wondering how the paid application like NetWrix Password Manager and AD SelfService Plus have implemented Reset Password Functionality. We have downloaded the trial version of NetWrix and tried to Reset the password by just providing the new password. It changes the password with all AD password policies taking into account including the history policy.

        Its been almost 2 month I am searching for the solution. Please suggest some solution, I’ll be very grateful to you.

        Reply
  43. ETS

    Thanks for the great post. Helped me a lot. Appreviate your time and effort.
    Have a question. Is there an easy way to find out all the groups and distribution list and not the users from a group.
    ie. X group has 5 members of which 3 are users and 2 are distribution list/groups. How to get only the 2 sub groups from the group X?

    I tried the following but that is not helping..

    from principal in orgGroupPrincipal.Members
    where principal is GroupPrincipal
    select principal as GroupPrincipal;

    Any suggestion?

    Thanks for your time.

    Reply
    1. ETS

      Got it…I used the property StructuralObjectClass == “group” to distinguish the user from class. 🙂

      Is there an alternate or better way; just curious..

      Reply
  44. namoguy

    First thanks so much for your work on this. I have been using it for over a year without problems.

    That is until today. The WebApp I wrote last month was working on my Laptop and the Server, but today I noticed it is no longer working on the server. I have reboot, redeployed the entire webapp and still nothing fixed it.

    I am hoping you might have seen this once or twice in your work with this…

    Error:
    System.NullReferenceException: Object reference not set to an instance of an object.

    Line:
    PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();

    Full method below.

    ///
    /// Gets a list of the users group memberships
    ///
    /// The user you want to get the group memberships
    /// Returns an arraylist of group memberships
    public ArrayList GetUserGroups(string sUserName)
    {
    ArrayList myItems = new ArrayList();
    UserPrincipal oUserPrincipal = GetUser(sUserName);

    PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();

    foreach (Principal oResult in oPrincipalSearchResult)
    {
    myItems.Add(oResult.Name.ToLower());
    }
    return myItems;
    }

    I will keep looking and post if I fix it. I hope you can help.

    Reply
  45. rsmacaalay

    I think its either the User you are searching does not have groups, the user is not existing anymore or permissions have changed

    Reply
    1. namoguy

      Thanks for the fast response. As it is working for me on my laptop, just not the server as me. So I exist, and I have groups. I am passing in the current users.

      UserID = WindowsIdentity.GetCurrent().Name.Substring(WindowsIdentity.GetCurrent().Name.LastIndexOf(@””) + 1);

      I just strip of the domain part. Just odd that the UserGroups is the only thing not working.

      Reply
      1. namoguy

        Great News, I have fixed the problem. After creating a new site and pushing the code out only to find it works fine on the new site, I went back to the production site and found someone had turned on “Enable Anonymous Access”. Once I turned that off all the code started working correctly.

        Reply
  46. Pingback: Active Directory средствами C# • Алексей Петрачук

  47. Pingback: Getting a User Or AllUsers from Active Directory using C# « Kazim's space

  48. Ilyas

    Thx for your valuable efforts…
    How can i search user by employee ID number

    Reply
  49. kcsgupta

    hi,
    I need to rename the user id with new one. can you give me a sample code

    Reply
  50. Scott Olson

    The account management helper class works great. Do you happen to have some code that would add missing items from the UserPrincipal… something like this below.

    The idea would be to add all of the missing items so that they could be set in code.

    It would be helpful to see not only how they get set, but how they would then get used in code..

    Thanks in advance.

    Scott

    Here is some sample code….

    [DirectoryProperty(“initials”)]
    public string initials
    {
    get
    {
    object[] result = this.ExtensionGet(“initials”);
    if (result != null)
    {
    return (string)result[0];
    }
    else
    {
    return null;
    }
    }
    set { this.ExtensionSet(“initials”, value); }
    }

    Reply
  51. ilyas

    Thx for your great effort.
    i receive error while use : logon failure unknown user name or bad password
    private string sDomain = “test.com”;
    private string sDefaultOU = “OU=testUsers,DC=testCORP,DC=test,DC=com”;
    private string sDefaultRootOU = “DC=testCORP,DC=test,DC=com”;
    private string sServiceUser = @”admintest”;
    private string sServicePassword = “test.123”;
    ==============
    private void btnuser_Click(object sender, EventArgs e)
    {
    try
    {
    ADMethodsAccountManagement userinfo = new ADMethodsAccountManagement();
    UserPrincipal aduser = userinfo.GetUser(txtusername.Text);

    Labtrueorfalse.Text = aduser.EmailAddress;
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    }

    Reply
  52. CRMA

    Good morning. I have a question ? How I can connect with Azure AD ?

    Reply
  53. Fouad

    An Excellent code, I am new to the .Net and I am trying to update the “ManagedBy” and “GrantSendOnBehalfTo” for a group, how can I use your Code to display and update the list of users in the mentioned group’s fields?

    Reply
  54. Pingback: How to use AD Attributes not represented in UserPrincipal, GroupPrincipal and ComputerPrincipal | SAMİ GÖNCÜ

  55. Pranay

    HI ,
    How to add user from domain XYZ into domain ABC distribution list.
    example : XYZuserid1 , I want to add this user into domain ABC distribution list.
    i.e. add non ABC user into ABC distribution list.
    Please help.
    Thanks,
    Pranay

    Reply
  56. John Burnham

    When using this if a username has a dash “-” in it I always receive not found. even through the user can be found in AD separately. So How do I get the dash “-” to be accepted.

    Reply
  57. Paul

    Hi Raymund,

    I am having difficulties trying to retrieve groups that a user is a member of using and I’m getting a NullReferenceException at this line..

    Return oGroupPrincipal.Members.Contains(oUserPrincipal)

    Am I trying to see if the user is a member of the ‘Staff’ group. I have verified that the user is valid already using ValidateCredentials but cannot seem to get the application to determine whether the user is a member of the group (which they are).

    Here’s my code…

    if (IsUserGroupMember(txtUsername.Text, “Staff”)) {
    MessageBox.Show(“User is a member of the Staff group.”);
    } else {
    MessageBox.Show(“User not a member of the Staff group.”);
    }

    Here’s a link to the image showing more detail about the exeption: http://s17.postimg.org/pdjwqfm3z/Null_Exception.jpg

    I am also having a problem trying to retrieve a list of groups that the user is a member of and get a NullReferenceException at this line too when I try using GetUserGroups:

    PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();

    Any help is much appreciated!

    Thank you,
    Paul

    Reply
    1. Raymund

      I think either the oUserPrincipal or oGroupPrincipal is null. You need to change it to If oUserPrincipal Is Nothing And oGroupPrincipal Is Nothing then ….

      Reply
  58. linkops

    I’m trying to do an account unlock function using this. How would i first test the account is locked using IsAccountLocked and then perform UnlockUserAccount if the Account is locked.

    Thanks

    Reply
  59. Maddy

    Thank you very much for this blog it’s very helpful.
    I have one question: Is there any way to identify that a particular user is loggedin in any of the windows domain clients.

    Reply
  60. vermaaman282

    Hi Raymund,

    I was just going through your post and it is very much relevant for what i am trying to do right now,
    My requirement is to insert the data in specific OU by checking in csv file,

    My OUs like below

    India
    Pune
    Mumbai
    Delhi
    Germany
    Contract
    Full-time
    above is the structure of my OU

    Now about my csv

    first name lastname jobtitle department manager location

    now the requirement is to put that data into the Pune location OU if location in csv is Pune

    can you please help me with

    Reply
  61. Thane Hubbell

    I think the test for IsUserExpired may not be correct. I’m working with a directory that has this nulled – and the user is not expired. Instead I changed it to this and I think this is correct:

    if (oUserPrincipal.AccountExpirationDate != null)
    {
    if (oUserPrincipal.AccountExpirationDate > DateTime.Now)
    return true;
    return false;
    }
    else
    {
    return false;
    }

    Reply
  62. Oliver

    hi.your code works great. do you have a sample code that will get the Audit aAcount logon events. I need to create a C# program to monitor the login/Logout of users in the Domain. please help.

    Reply
    1. Raymund Macaalay Post author

      Hi you can use the code above by querying the lastLogon and lastLogoff attribute of a certain user but if you have multiple domain controller you will have to query all of them separately and consolidate them before outputting your results

      Reply
  63. Oliver

    hi..but i need to monitor all users logon and logoff in the domain.i mean getting the list of user and their respective logon datetime and logof datetime .if you have sample code to share, im very much appreciate it. thank you

    Reply
    1. Raymund Macaalay Post author

      Like I said you can by listing all users and showing all lastLogon and lastLogoff attributes. By the code above and a little bit of thinking you can get what you need. But take note AD has a limitation of showing only 1000 records at a time. This is another issue but still can be resolved

      Reply
  64. Oliver

    hi raymund… i was not able to get the lastlogoff othe user. do you have a sample code for getting it.

    Reply
  65. riza

    hi i am having problem when entering correct username but bad password. GetUser method fails to execute becouse the username and password in not correct. Even if the account is locked, this GetUser method fails. Becouse of this i cant get the status of user (i.e is Accountlocked). could you please help me on this

    Thanks

    Reply
  66. Ropy

    Whenever I try to call IsUserGroupMember I get the following error:

    Error System.Security.Authentication.AuthenticationException: The user name or password is incorrect.
    —> System.DirectoryServices.DirectoryServicesCOMException: The user name or password is incorrect.

    at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
    at System.DirectoryServices.DirectoryEntry.Bind()
    at System.DirectoryServices.DirectoryEntry.get_SchemaEntry()
    at System.DirectoryServices.AccountManagement.ADStoreCtx.IsContainer(DirectoryEntry de)
    at System.DirectoryServices.AccountManagement.ADStoreCtx..ctor(DirectoryEntry ctxBase, Boolean ownCtxBase, String username, String password, ContextOptions options)
    at System.DirectoryServices.AccountManagement.PrincipalContext.CreateContextFromDirectoryEntry(DirectoryEntry entry)
    at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
    — End of inner exception stack trace —
    at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
    at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
    at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
    at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
    at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)
    at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, String identityValue)
    at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, String identityValue)
    at CMManagement.GetUser(String sUserName) in Management.cs:line 91
    at CMManagement.IsUserGroupMember(String sUserName, String sGroupName) in Management.cs:line 324
    at CM12AutomationTest.Default.ExecuteCode_Click(Object sender, EventArgs e) in Default.aspx.cs:line 212

    The function is called:

    try
    {
    CMManagement cm = new CMManagement();
    ResultBox.Text = cm.IsUserGroupMember(uName, gName).ToString();
    }
    catch (Exception eX)
    {
    ResultBox.Text = “Error ” + eX;
    }

    What am I missing?

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.