Active Driectory 操作(转来放起来,不要丢了)

系统 1727 0
 

Introduction

When it comes to programmatically accessing Microsoft's Active Directory a lot of people seem to have quite a difficult time tying all the pieces together to accomplish exactly what they want to. There are so many technologies available for communicating with LDAP that many programmers end up with a mix between COM+ ADSI calls and .NET class calls mixed into their code. ADSI code is so difficult to understand and follow that the creator of that code usually owns it for the entirety of it's lifecycle since no one else wants to support it.

This article attempts to tie together the most commonly used elements involved in Active Directory Management in the simplest, most clean manner possible. I interact with Active Directory in nearly all of my applications (web & forms) and I have had to solve a lot of integration issues for many customers. When I was starting out with this technology I had a lot of growing pains so this is an attempt to help those programmers who may have a need to interact with the Directory but do not want to have to become experts in the issue. However, certain rudimentary knowledge and concepts are required in order to utilize the code. You must be familiar with such terms as: distinguishedName, ldap paths, fully qualified domain names, object attributes (single string & multi-string), and general knowledge of ldap schemas.

Background

There is a great collection of sample code available on MSDN's website for the v1.1 System.DirectoryServices assembly but there seems to be a void when it comes to the new functionality available in the v2.0 System.DirectoryServices.ActiveDirectory assembly. Since this article's original publishing, Generics have gained widespread acceptance and I encourage anyone borrowing from this resource to replace the archaic ArrayList collections with List<T> or appropriate generic collections.

Points of Concern

In order to communicate with Active Directory one must take into account network security, business rules, and technological constraints. If you're using Active Directory code from an ASP.NET page you must ensure that the code has the appropriate level of permission to access and interact with the directory. For development purposes or proof of concept you can enable impersonation at the ASP.NET level (in web.config) and the IIS level and if the IIS server and the directory domain controller reside on the same machine this will work. However, if these entities are not co-located on the same server (as they never are in production) you can wrap the code around an impersonation class (such as the Zeta Impersonator which will execute the Directory calls under the token of the impersonated user. It's strongly recommended that you do not do this for security reasons unless absolutely necessary. . The authorized method for granting the ASP.NET application permission to the directory is by way of either a privileged IIS Application Pool running under the identity of a service account or by way of a COM+ entity running under the identity of a service account.

If you plan on running this code from a desktop assembly then you're going to want to ensure that your machine is attached to a domain and can communicate with that domain. The impersonation is not necessary if the user running the code has sufficient privileges on the domain.

Running Code in Batch Processes

It is also important to note that if you plan on running this code from an ASP.NET page in batch, ASP.NET will time out on you if you try to run batch processes from it's primary thread. There are several things to consider in this scenario but be aware that for example, if you're creating x number of accounts through an ASP.NET application (or performing any batch operation in general) that you must plan to use queues, a back-end scheduler, or some other mechanism outside the scope of the page itself to prevent timing out during your processes. As with any ASPNET design, it's never a good idea to use ASPNET itself for anything but the "View" part of the solution. The best architecture would queue tasks into a SQL database or something to that effect and then a back-end windows service or similar application would pick up the tasking and perform the actual Directory operations.

This is typically how I engineer Active Directory management solutions for customers.

A Note on Method Parameters

You will notice that most of the methods require the same parameters. Rather than identify each time I will outline them now:

  • friendlyDomainName : the non qualified domain name (contoso - NOT contoso.com)
  • ldapDomain : the fully qualified domain such as contoso.com or dc=contoso , dc=com
  • objectPath : the fully qualified path to the object: CN=user , OU=USERS , DC=contoso , DC=com (same as objectDn )
  • objectDn : the distinguishedName of the object: CN=group , OU=GROUPS , DC=contoso , DC=com
  • userDn : the distinguishedName of the user: CN=user, OU=USERS, DC=contoso, DC=com
  • groupDn : the distinguishedName of the group: CN=group,OU=GROUPS,DC=contoso,DC=com

A Note on System.DirectoryServices.DirectoryEntry

You'll notice in all the samples that we're binding directly to the directoryEntry and not specifying a server or credentials. If you do not want to use an impersonation class you can send credentials directly into the DirectoryEntry constructor. The impersonation class is helpful for those times when you want to use a static method and don't want to go through the trouble of creating a DirectoryContext object to hold these details. Likewise you may want to target a specific domain controller.

Target Specific Domain Controllers or Credentials

Everywhere in the code that you see: LDAP: // you can replace with LDAP: // MyDomainControllerNameOrIpAddress as well as everywhere you see a DirectoryEntry class being constructed you can send in specific credentials as well. This is especially helpful if you need to work on an Active Directory for which your machine is not a member of it's forest or domain or you want to target a DC to make the changes to.

    
      //
    
    
      Rename an object and specify the domain controller and credentials directly
    
    
      public
    
    
      static
    
    
      void
    
     Rename(
    
      string
    
     server,

    
    
      string
    
     userName, 
    
      string
    
     password, 
    
      string
    
     objectDn, 
    
      string
    
     newName)

{

    DirectoryEntry child = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + server + 
    
      "
    
    
      /"
    
     + 

        objectDn, userName, password);

    child.Rename(
    
      "
    
    
      CN="
    
     + newName);

}
  

Managing local accounts with DirectoryEntry

It is important to note that you can execute some of these methods against a local machine as opposed to an Active Directory if needed by simply replacing the LDAP: // string with WinNT: // as demonstrated below

    
      //
    
    
      create new local account
    
    



DirectoryEntry localMachine = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      WinNT://"
    
     + 

    Environment.MachineName);

DirectoryEntry newUser = localMachine.Children.Add(
    
      "
    
    
      localuser"
    
    , 
    
      "
    
    
      user"
    
    );

newUser.Invoke(
    
      "
    
    
      SetPassword"
    
    , 
    
      new
    
    
      object
    
    [] { 
    
      "
    
    
      3l!teP@$$w0RDz"
    
     });

newUser.CommitChanges();

Console.WriteLine(newUser.Guid.ToString());

localMachine.Close();

newUser.Close();
  

Managing local groups with DirectoryEntry

A few configuration changes need to be made to the code but it's pretty straightforward. Below you can see an example of using DirectoryEntry to enumerate the members of the local "administrator" group.

    DirectoryEntry localMachine = 
    
      new
    
     DirectoryEntry

    (
    
      "
    
    
      WinNT://"
    
     + Environment.MachineName + 
    
      "
    
    
      ,Computer"
    
    );

DirectoryEntry admGroup = localMachine.Children.Find

    (
    
      "
    
    
      administrators"
    
    , 
    
      "
    
    
      group"
    
    );


    
      object
    
     members = admGroup.Invoke(
    
      "
    
    
      members"
    
    , 
    
      null
    
    );




    
      foreach
    
     (
    
      object
    
     groupMember 
    
      in
    
     (IEnumerable)members)

{

    DirectoryEntry member = 
    
      new
    
     DirectoryEntry(groupMember);

    Console.WriteLine(member.Name);

}
  

Managing IIS with DirectoryEntry

In addition to managing local & directory services accounts, the versatile DirectoryEntry object can manage other network providers as well, such as IIS. Below is an example of how you can use DirectoryEntry to provision a new virtual directory in IIS.

    
      //
    
    
      Create New Virtual Directory in IIS with DirectoryEntry()
    
    
      string
    
     wwwroot = 
    
      "
    
    
      c:\\Inetpub\\wwwroot"
    
    ;


    
      string
    
     virtualDirectoryName = 
    
      "
    
    
      myNewApp"
    
    ;


    
      string
    
     sitepath = 
    
      "
    
    
      IIS://localhost/W3SVC/1/ROOT"
    
    ;



DirectoryEntry vRoot = 
    
      new
    
     DirectoryEntry(sitepath);

DirectoryWntry vDir = vRoot.Children.Add(virtualDirectoryName, 

                            
    
      "
    
    
      IIsWebVirtualDir"
    
    );

vDir.CommitChanges();



vDir.Properties[
    
      "
    
    
      Path"
    
    ].Value = wwwroot + 
    
      "
    
    
      \\" + virtualDirectoryName;

vDir.Properties["
    
    DefaultDoc
    
      "
    
    
      ].Value = "
    
    Default.aspx
    
      "
    
    
      ;

vDir.Properties["
    
    DirBrowseFlags
    
      "
    
    
      ].Value = 2147483648;

vDir.Commitchanges();

vRoot.CommitChanges();
    
  

Active Directory Code

The code below is broken apart logically into usage categories. Again, this is not intended to be a complete library, just the code that I use on a daily basis.

Active Directory Management

    
      //
    
    
      These methods require these imports
    
    
      //
    
    
      You must add a references in your project as well
    
    
      using
    
     System.DirectoryServices;


    
      using
    
     System.DirectoryServices.ActiveDirectory;
  

Translate the Friendly Domain Name to Fully Qualified Domain

    
      public
    
    
      static
    
    
      string
    
     FriendlyDomainToLdapDomain(
    
      string
    
     friendlyDomainName)

{

    
    
      string
    
     ldapPath = 
    
      null
    
    ;

    
    
      try
    
    

    {

        DirectoryContext objContext = 
    
      new
    
     DirectoryContext(

            DirectoryContextType.Domain, friendlyDomainName);

        Domain objDomain = Domain.GetDomain(objContext);

        ldapPath = objDomain.Name;

    }

    
    
      catch
    
     (DirectoryServicesCOMException e)

    {

        ldapPath = e.Message.ToString();

    }

    
    
      return
    
     ldapPath;

}
  

Enumerate Domains in the Current Forest

    
      public
    
    
      static
    
     ArrayList EnumerateDomains()

{

    ArrayList alDomains = 
    
      new
    
     ArrayList();

    Forest currentForest = Forest.GetCurrentForest();

    DomainCollection myDomains = currentForest.Domains;



    
    
      foreach
    
     (Domain objDomain 
    
      in
    
     myDomains)

    {

        alDomains.Add(objDomain.Name);

    }

    
    
      return
    
     alDomains;

}
  

Enumerate Global Catalogs in the Current Forest

    
      public
    
    
      static
    
     ArrayList EnumerateDomains()

{

    ArrayList alGCs = 
    
      new
    
     ArrayList();

    Forest currentForest = Forest.GetCurrentForest();

    
    
      foreach
    
     (GlobalCatalog gc 
    
      in
    
     currentForest.GlobalCatalogs)

    {

        alGCs.Add(gc.Name);

    }

    
    
      return
    
     alGCs;

}
  

Enumerate Domain Controllers in a Domain

    
      public
    
    
      static
    
     ArrayList EnumerateDomainControllers()

{

    ArrayList alDcs = 
    
      new
    
     ArrayList();

    Domain domain = Domain.GetCurrentDomain();

    
    
      foreach
    
     (DomainController dc 
    
      in
    
     domain.DomainControllers)

    {

        alDcs.Add(dc.Name);

    }

    
    
      return
    
     alDcs;

}
  

Create a Trust Relationship

    
      public
    
    
      void
    
     CreateTrust(
    
      string
    
     sourceForestName, 
    
      string
    
     targetForestName)

{

    Forest sourceForest = Forest.GetForest(
    
      new
    
     DirectoryContext(

        DirectoryContextType.Forest, sourceForestName));



    Forest targetForest = Forest.GetForest(
    
      new
    
     DirectoryContext(

        DirectoryContextType.Forest, targetForestName));



    
    
      //
    
    
       create an inbound forest trust
    
    



    sourceForest.CreateTrustRelationship(targetForest,

        TrustDirection.Outbound);

}
  

Delete a Trust Relationship

    
      public
    
    
      void
    
     DeleteTrust(
    
      string
    
     sourceForestName, 
    
      string
    
     targetForestName)

{

    Forest sourceForest = Forest.GetForest(
    
      new
    
     DirectoryContext(

        DirectoryContextType.Forest, sourceForestName));



    Forest targetForest = Forest.GetForest(
    
      new
    
     DirectoryContext(

        DirectoryContextType.Forest, targetForestName));



    
    
      //
    
    
       delete forest trust
    
    



    sourceForest.DeleteTrustRelationship(targetForest);

}
  

Enumerate Objects in an OU

The parameter OuDn is the Organizational Unit distinguishedName such as OU=Users,dc=myDomain,dc=com

    
      public
    
     ArrayList EnumerateOU(
    
      string
    
     OuDn)

{

    ArrayList alObjects = 
    
      new
    
     ArrayList();

    
    
      try
    
    

    {

        DirectoryEntry directoryObject = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + OuDn);

        
    
      foreach
    
     (DirectoryEntry child 
    
      in
    
     directoryObject.Children)

        {

            
    
      string
    
     childPath = child.Path.ToString();

            alObjects.Add(childPath.Remove(
    
      0
    
    ,
    
      7
    
    )); 

                
    
      //
    
    
      remove the LDAP prefix from the path
    
    



            child.Close();

            child.Dispose();

        }

        directoryObject.Close();

        directoryObject.Dispose();

    }

    
    
      catch
    
     (DirectoryServicesCOMException e)

    {

        Console.WriteLine(
    
      "
    
    
      An Error Occurred: "
    
     + e.Message.ToString());

    }

    
    
      return
    
     alObjects;

}
  

Enumerate Directory Entry Settings

One of the nice things about the 2.0 classes is the ability to get and set a configuration object for your directoryEntry objects.

    
      static
    
    
      void
    
     DirectoryEntryConfigurationSettings(
    
      string
    
     domainADsPath)

{

    
    
      //
    
    
       Bind to current domain
    
    



    DirectoryEntry entry = 
    
      new
    
     DirectoryEntry(domainADsPath);

    DirectoryEntryConfiguration entryConfiguration = entry.Options;



    Console.WriteLine(
    
      "
    
    
      Server: "
    
     + entryConfiguration.GetCurrentServerName());

    Console.WriteLine(
    
      "
    
    
      Page Size: "
    
     + entryConfiguration.PageSize.ToString());

    Console.WriteLine(
    
      "
    
    
      Password Encoding: "
    
     + 

        entryConfiguration.PasswordEncoding.ToString());

    Console.WriteLine(
    
      "
    
    
      Password Port: "
    
     + 

        entryConfiguration.PasswordPort.ToString());

    Console.WriteLine(
    
      "
    
    
      Referral: "
    
     + entryConfiguration.Referral.ToString());

    Console.WriteLine(
    
      "
    
    
      Security Masks: "
    
     + 

        entryConfiguration.SecurityMasks.ToString());

    Console.WriteLine(
    
      "
    
    
      Is Mutually Authenticated: "
    
     + 

        entryConfiguration.IsMutuallyAuthenticated().ToString());

    Console.WriteLine();

    Console.ReadLine();

}
  

Active Directory Objects

    
      //
    
    
      These methods require these imports
    
    
      //
    
    
      You must add a references in your project as well
    
    
      using
    
     System.DirectoryServices;
  

Check for the Existence of an Object

This method does not need you to know the distinguishedName , you can concat strings or even guess a location and it will still run (and return false if not found).

    
      public
    
    
      static
    
    
      bool
    
     Exists(
    
      string
    
     objectPath)

{

    
    
      bool
    
     found = 
    
      false
    
    ;

    
    
      if
    
     (DirectoryEntry.Exists(
    
      "
    
    
      LDAP://"
    
     + objectPath))

    {

        found = 
    
      true
    
    ;

    }

    
    
      return
    
     found;

}
  

Move an Object from one Location to Another

It should be noted that the string newLocation should NOT include the CN= value of the object. The method will pull that from the objectLocation string for you. So object CN=group,OU=GROUPS,DC=contoso,DC=com is sent in as the objectLocation but the newLocation is something like: OU=NewOUParent,DC=contoso,DC=com . The method will take care of the CN=group .

    
      public
    
    
      void
    
     Move(
    
      string
    
     objectLocation, 
    
      string
    
     newLocation)

{

    
    
      //
    
    
      For brevity, removed existence checks
    
    



    DirectoryEntry eLocation = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + objectLocation);

    DirectoryEntry nLocation = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + newLocation);

    
    
      string
    
     newName = eLocation.Name;

    eLocation.MoveTo(nLocation, newName);

    nLocation.Close();

    eLocation.Close();

}
  

Enumerate Multi-String Attribute Values of an Object

This method includes a recursive flag in case you want to recursively dig up properties of properties such as enumerating all the member values of a group and then getting each member group's groups all the way up the tree.

    
      public
    
     ArrayList AttributeValuesMultiString(
    
      string
    
     attributeName,

     
    
      string
    
     objectDn, ArrayList valuesCollection, 
    
      bool
    
     recursive)

{

    DirectoryEntry ent = 
    
      new
    
     DirectoryEntry(objectDn);

    PropertyValueCollection ValueCollection = ent.Properties[attributeName];

    IEnumerator en = ValueCollection.GetEnumerator();



    
    
      while
    
     (en.MoveNext())

    {

        
    
      if
    
     (en.Current != 
    
      null
    
    )

        {

            
    
      if
    
     (!valuesCollection.Contains(en.Current.ToString()))

            {

                valuesCollection.Add(en.Current.ToString());

                
    
      if
    
     (recursive)

                {

                    AttributeValuesMultiString(attributeName, 
    
      "
    
    
      LDAP://"
    
     +

                    en.Current.ToString(), valuesCollection, 
    
      true
    
    );

                }

            }

        }

    }

    ent.Close();

    ent.Dispose();

    
    
      return
    
     valuesCollection;

}
  

Enumerate Single String Attribute Values of an Object

    
      public
    
    
      string
    
     AttributeValuesSingleString

    (
    
      string
    
     attributeName, 
    
      string
    
     objectDn)

{

    
    
      string
    
     strValue;

    DirectoryEntry ent = 
    
      new
    
     DirectoryEntry(objectDn);

    strValue = ent.Properties[attributeName].Value.ToString();

    ent.Close();

    ent.Dispose();

    
    
      return
    
     strValue;

}
  

Enumerate an Object's Properties: The Ones with Values

    
      public
    
    
      static
    
     ArrayList GetUsedAttributes(
    
      string
    
     objectDn)

{

    DirectoryEntry objRootDSE = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + objectDn);

    ArrayList props = 
    
      new
    
     ArrayList();



    
    
      foreach
    
     (
    
      string
    
     strAttrName 
    
      in
    
     objRootDSE.Properties.PropertyNames)

    {

        props.Add(strAttrName);

    }

    
    
      return
    
     props;

}
  

Get an Object DistinguishedName: ADO.NET search (ADVANCED)

This method is the glue that ties all the methods together since most all the methods require the consumer to provide a distinguishedName . Wherever you put this code, you must ensure that you add these enumerations as well. This allows the consumers to specify the type of object to search for and whether they want the distinguishedName returned or the objectGUID .

    
      public
    
    
      enum
    
     objectClass

{

    user, group, computer

}


    
      public
    
    
      enum
    
     returnType

{

 distinguishedName, ObjectGUID

}
  

A call to this class might look like:

myObjectReference.GetObjectDistinguishedName(objectClass.user, returnType.ObjectGUID, " john.q.public" , " contoso.com" )

    
      public
    
    
      string
    
     GetObjectDistinguishedName(objectClass objectCls,

    returnType returnValue, 
    
      string
    
     objectName, 
    
      string
    
     LdapDomain)

{

    
    
      string
    
     distinguishedName = 
    
      string
    
    .Empty;

    
    
      string
    
     connectionPrefix = 
    
      "
    
    
      LDAP://"
    
     + LdapDomain;

    DirectoryEntry entry = 
    
      new
    
     DirectoryEntry(connectionPrefix);

    DirectorySearcher mySearcher = 
    
      new
    
     DirectorySearcher(entry);



    
    
      switch
    
     (objectCls)

    {

        
    
      case
    
     objectClass.user:

            mySearcher.Filter = 
    
      "
    
    
      (&(objectClass=user)

        (|(cn="
    
     + objectName + 
    
      "
    
    
      )(sAMAccountName="
    
     + objectName + 
    
      "
    
    
      )))"
    
    ;

            
    
      break
    
    ;

        
    
      case
    
     objectClass.group:

            mySearcher.Filter = 
    
      "
    
    
      (&(objectClass=group)

        (|(cn="
    
     + objectName + 
    
      "
    
    
      )(dn="
    
     + objectName + 
    
      "
    
    
      )))"
    
    ;

            
    
      break
    
    ;

        
    
      case
    
     objectClass.computer:

            mySearcher.Filter = 
    
      "
    
    
      (&(objectClass=computer)

            (|(cn="
    
     + objectName + 
    
      "
    
    
      )(dn="
    
     + objectName + 
    
      "
    
    
      )))"
    
    ;

            
    
      break
    
    ;

    }

    SearchResult result = mySearcher.FindOne();



    
    
      if
    
     (result == 
    
      null
    
    )

    {

        
    
      throw
    
    
      new
    
     NullReferenceException

        (
    
      "
    
    
      unable to locate the distinguishedName for the object "
    
     +

        objectName + 
    
      "
    
    
       in the "
    
     + LdapDomain + 
    
      "
    
    
       domain"
    
    );

    }

    DirectoryEntry directoryObject = result.GetDirectoryEntry();

    
    
      if
    
     (returnValue.Equals(returnType.distinguishedName))

    {

        distinguishedName = 
    
      "
    
    
      LDAP://"
    
     + directoryObject.Properties

            [
    
      "
    
    
      distinguishedName"
    
    ].Value;

    }

    
    
      if
    
     (returnValue.Equals(returnType.ObjectGUID))

    {

        distinguishedName = directoryObject.Guid.ToString();

    }

    entry.Close();

    entry.Dispose();

    mySearcher.Dispose();

    
    
      return
    
     distinguishedName;

}
  

Convert distinguishedName to ObjectGUID

    
      public
    
    
      string
    
     ConvertDNtoGUID(
    
      string
    
     objectDN)

{

    
    
      //
    
    
      Removed logic to check existence first
    
    



    DirectoryEntry directoryObject = 
    
      new
    
     DirectoryEntry(objectDN);

    
    
      return
    
     directoryObject.Guid.ToString();

}
  

Convert an ObjectGUID to OctectString: The Native ObjectGUID

    
      public
    
    
      static
    
    
      string
    
     ConvertGuidToOctectString(
    
      string
    
     objectGuid)

{

    System.Guid guid = 
    
      new
    
     Guid(objectGuid);

    
    
      byte
    
    [] byteGuid = guid.ToByteArray();

    
    
      string
    
     queryGuid = 
    
      "
    
    
      "
    
    ;

    
    
      foreach
    
     (
    
      byte
    
     b 
    
      in
    
     byteGuid)

    {

        queryGuid += 
    
      @"
    
    
      \"
    
     + b.ToString(
    
      "
    
    
      x2"
    
    );

    }

    
    
      return
    
     queryGuid;

}
  

Search by ObjectGUID or convert ObjectGUID to distinguishedName

    
      public
    
    
      static
    
    
      string
    
     ConvertGuidToDn(
    
      string
    
     GUID)

{

      DirectoryEntry ent = 
    
      new
    
     DirectoryEntry();

      
    
      String
    
     ADGuid = ent.NativeGuid;

      DirectoryEntry x = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://{GUID="
    
     + ADGuid + 
    
      "
    
    
      >"
    
    ); 

          
    
      //
    
    
      change the { to <>
    
    
      return
    
     x.Path.Remove(
    
      0
    
    ,
    
      7
    
    ); 
    
      //
    
    
      remove the LDAP prefix from the path
    
    



}
  

Publish Network Shares in Active Directory

    
      //
    
    
      Example
    
    
      private
    
    
      void
    
     init()

{

    CreateShareEntry(
    
      "
    
    
      OU=HOME,dc=baileysoft,dc=com"
    
    ,

        
    
      "
    
    
      Music"
    
    , 
    
      @"
    
    
      \\192.168.2.1\Music"
    
    , 
    
      "
    
    
      mp3 Server Share"
    
    );

    Console.ReadLine();

}




    
      //
    
    
      Actual Method
    
    
      public
    
    
      void
    
     CreateShareEntry(
    
      string
    
     ldapPath,

    
    
      string
    
     shareName, 
    
      string
    
     shareUncPath, 
    
      string
    
     shareDescription)

{

    
    
      string
    
     oGUID = 
    
      string
    
    .Empty;

    
    
      string
    
     connectionPrefix = 
    
      "
    
    
      LDAP://"
    
     + ldapPath;

    DirectoryEntry directoryObject = 
    
      new
    
     DirectoryEntry(connectionPrefix);

    DirectoryEntry networkShare = directoryObject.Children.Add(
    
      "
    
    
      CN="
    
     + 

        shareName, 
    
      "
    
    
      volume"
    
    );

    networkShare.Properties[
    
      "
    
    
      uNCName"
    
    ].Value = shareUncPath;

    networkShare.Properties[
    
      "
    
    
      Description"
    
    ].Value = shareDescription;

    networkShare.CommitChanges();



    directoryObject.Close();

    networkShare.Close();

}
  

Create a New Security Group

Note: by default if no GroupType property is set, the group is created as a domain security group.

    
      public
    
    
      void
    
     Create(
    
      string
    
     ouPath, 
    
      string
    
     name)

{

    
    
      if
    
     (!DirectoryEntry.Exists(
    
      "
    
    
      LDAP://CN="
    
     + name + 
    
      "
    
    
      ,"
    
     + ouPath))

    {

        
    
      try
    
    

        {

            DirectoryEntry entry = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + ouPath);

            DirectoryEntry group = entry.Children.Add(
    
      "
    
    
      CN="
    
     + name, 
    
      "
    
    
      group"
    
    );

            group.Properties[
    
      "
    
    
      sAmAccountName"
    
    ].Value = name;

            group.CommitChanges();

        }

        
    
      catch
    
     (Exception e)

        {

            Console.WriteLine(e.Message.ToString());

        }

    }

    
    
      else
    
     { Console.WriteLine(path + 
    
      "
    
    
       already exists"
    
    ); }

}
  

Delete a group

    
      public
    
    
      void
    
     Delete(
    
      string
    
     ouPath, 
    
      string
    
     groupPath)

{

    
    
      if
    
     (DirectoryEntry.Exists(
    
      "
    
    
      LDAP://"
    
     + groupPath))

    {

        
    
      try
    
    

        {

            DirectoryEntry entry = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + ouPath);

            DirectoryEntry group = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + groupPath);

            entry.Children.Remove(group);

            group.CommitChanges();

        }

        
    
      catch
    
     (Exception e)

        {

            Console.WriteLine(e.Message.ToString());

        }

    }

    
    
      else
    
    

    { 

        Console.WriteLine(path + 
    
      "
    
    
       doesn't exist"
    
    ); 

    }

}
  

Active Directory Users Tasks

    
      //
    
    
      These methods require these imports
    
    
      //
    
    
      You must add a references in your project as well
    
    
      using
    
     System.DirectoryServices;
  

Authenticate a User Against the Directory

private bool Authenticate( string userName, string password, string domain)
{
    bool authentic = false ;
    try
    {
        DirectoryEntry entry = new DirectoryEntry( " LDAP://" + domain,
            userName, password);
        object nativeObject = entry.NativeObject;
        authentic = true ;
    }
    catch (DirectoryServicesCOMException) { }
    return authentic;
}

Add User to Group

    
      public
    
    
      void
    
     AddToGroup(
    
      string
    
     userDn, 
    
      string
    
     groupDn)

{

    
    
      try
    
    

    {

        DirectoryEntry dirEntry = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + groupDn);

        dirEntry.Properties[
    
      "
    
    
      member"
    
    ].Add(userDn);

        dirEntry.CommitChanges();

        dirEntry.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      doSomething with E.Message.ToString();
    
    



    }

}
  

Remove User from Group

    
      public
    
    
      void
    
     RemoveUserFromGroup(
    
      string
    
     userDn, 
    
      string
    
     groupDn)

{

    
    
      try
    
    

    {

        DirectoryEntry dirEntry = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + groupDn);

        dirEntry.Properties[
    
      "
    
    
      member"
    
    ].Remove(userDn);

        dirEntry.CommitChanges();

        dirEntry.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      doSomething with E.Message.ToString();
    
    



    }

}
  

Get User Group Memberships of the Logged in User from ASP.NET

    
      public
    
     ArrayList Groups()

{

    ArrayList groups = 
    
      new
    
     ArrayList();

    
    
      foreach
    
     (System.Security.Principal.IdentityReference group 
    
      in
    
    

        System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)

    {

        groups.Add(group.Translate(
    
      typeof
    
    

            (System.Security.Principal.NTAccount)).ToString());

    }

    
    
      return
    
     groups;

}
  

Get User Group Memberships

This method requires that you have the AttributeValuesMultiString method earlier in the article included in your class.

    
      public
    
     ArrayList Groups(
    
      string
    
     userDn, 
    
      bool
    
     recursive)

{

    ArrayList groupMemberships = 
    
      new
    
     ArrayList();

    
    
      return
    
     AttributeValuesMultiString(
    
      "
    
    
      memberOf"
    
    , userDn,

        groupMemberships, recursive);

}
  

Create User Account

    
      public
    
    
      string
    
     CreateUserAccount(
    
      string
    
     ldapPath, 
    
      string
    
     userName, 

    
    
      string
    
     userPassword)

{

    
    
      try
    
    

    {

        
    
      string
    
     oGUID = 
    
      string
    
    .Empty;

        
    
      string
    
     connectionPrefix = 
    
      "
    
    
      LDAP://"
    
     + ldapPath;

        DirectoryEntry dirEntry = 
    
      new
    
     DirectoryEntry(connectionPrefix);

        DirectoryEntry newUser = dirEntry.Children.Add

            (
    
      "
    
    
      CN="
    
     + userName, 
    
      "
    
    
      user"
    
    );

        newUser.Properties[
    
      "
    
    
      samAccountName"
    
    ].Value = userName;

        newUser.CommitChanges();

        oGUID = newUser.Guid.ToString();



        newUser.Invoke(
    
      "
    
    
      SetPassword"
    
    , 
    
      new
    
    
      object
    
    [] { userPassword });

        newUser.CommitChanges();

        dirEntry.Close();

        newUser.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      DoSomethingwith --> E.Message.ToString();
    
    



    }

    
    
      return
    
     oGUID;

}
  

Dealing with User Passwords

There are some specifics to understand when dealing with user passwords and boundaries around passwords such as forcing a user to change their password on the next logon, denying the user the right to change their own passwords, setting passwords to never expire, to when to expire, and these tasks can be accomplished using UserAccountControl flags that are demonstrated in the proceeding sections. Please refer to this great MSDN article: Managing User Passwords for examples and documentation regarding these features. (thanks to Daniel Ocean for identifying this resource)

    
      //
    
    
      Add this to the create account method
    
    
      int
    
     val = (
    
      int
    
    )newUser.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value; 

     
    
      //
    
    
      newUser is DirectoryEntry object
    
    



newUser.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value = val | 0x80000; 

    
    
      //
    
    
      ADS_UF_TRUSTED_FOR_DELEGATION
    
  

All UserAccountControl flags

    CONST   HEX

-------------------------------

        SCRIPT 0x0001

        ACCOUNTDISABLE 0x0002

        HOMEDIR_REQUIRED 0x0008

        LOCKOUT 0x0010

        PASSWD_NOTREQD 0x0020

        PASSWD_CANT_CHANGE 0x0040

        ENCRYPTED_TEXT_PWD_ALLOWED 0x0080

        TEMP_DUPLICATE_ACCOUNT 0x0100

        NORMAL_ACCOUNT 0x0200

        INTERDOMAIN_TRUST_ACCOUNT 0x0800

        WORKSTATION_TRUST_ACCOUNT 0x1000

        SERVER_TRUST_ACCOUNT 0x2000

        DONT_EXPIRE_PASSWORD 0x10000

        MNS_LOGON_ACCOUNT 0x20000

        SMARTCARD_REQUIRED 0x40000

        TRUSTED_FOR_DELEGATION 0x80000

        NOT_DELEGATED 0x100000

        USE_DES_KEY_ONLY 0x200000

        DONT_REQ_PREAUTH 0x400000

        PASSWORD_EXPIRED 0x800000

        TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000
  

Enable a User Account

    
      public
    
    
      void
    
     Enable(
    
      string
    
     userDn)

{

    
    
      try
    
    

    {

        DirectoryEntry user = 
    
      new
    
     DirectoryEntry(userDn);

        
    
      int
    
     val = (
    
      int
    
    )user.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value;

        user.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value = val & ~0x2; 

            
    
      //
    
    
      ADS_UF_NORMAL_ACCOUNT;
    
    



        user.CommitChanges();

        user.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      DoSomethingWith --> E.Message.ToString();
    
    



    }

}
  

Disable a User Account

    
      public
    
    
      void
    
     Disable(
    
      string
    
     userDn)

{

    
    
      try
    
    

    {

        DirectoryEntry user = 
    
      new
    
     DirectoryEntry(userDn);

        
    
      int
    
     val = (
    
      int
    
    )user.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value;

        user.Properties[
    
      "
    
    
      userAccountControl"
    
    ].Value = val | 0x2; 

             
    
      //
    
    
      ADS_UF_ACCOUNTDISABLE;
    
    



        user.CommitChanges();

        user.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      DoSomethingWith --> E.Message.ToString();
    
    



    }

}
  

Unlock a User Account

    
      public
    
    
      void
    
     Unlock(
    
      string
    
     userDn)

{

    
    
      try
    
    

    {

        DirectoryEntry uEntry = 
    
      new
    
     DirectoryEntry(userDn);

        uEntry.Properties[
    
      "
    
    
      LockOutTime"
    
    ].Value = 
    
      0
    
    ; 
    
      //
    
    
      unlock account
    
    



        uEntry.CommitChanges(); 
    
      //
    
    
      may not be needed but adding it anyways
    
    



        uEntry.Close();

    }

    
    
      catch
    
     (System.DirectoryServices.DirectoryServicesCOMException E)

    {

        
    
      //
    
    
      DoSomethingWith --> E.Message.ToString();
    
    



    }

}
  

Alternate Lock/Unlock Account

It's hard to find code to lock an account. Here is my code to lock or unlock an account. dEntry is class variable already set to a user account. Shared by dextrous1.

    
      ///
    
    
      
        <
      
      
        summary
      
      
        >
      
    
    
      ///
    
    
       Gets or sets a value indicating if the user account is locked out
    
    
      ///
    
    
      
        <
      
      
        /
      
      
        summary
      
      
        >
      
    
    
      public
    
    
      bool
    
     IsLocked

{

    
    
      get
    
     { 
    
      return
    
     Convert.ToBoolean(dEntry.InvokeGet(
    
      "
    
    
      IsAccountLocked"
    
    )); }

    
    
      set
    
     { dEntry.InvokeSet(
    
      "
    
    
      IsAccountLocked"
    
    , value); }

}
  

Reset a User Password

    
      public
    
    
      void
    
     ResetPassword(
    
      string
    
     userDn, 
    
      string
    
     password)

{

    DirectoryEntry uEntry = 
    
      new
    
     DirectoryEntry(userDn);

    uEntry.Invoke(
    
      "
    
    
      SetPassword"
    
    , 
    
      new
    
    
      object
    
    [] { password });

    uEntry.Properties[
    
      "
    
    
      LockOutTime"
    
    ].Value = 
    
      0
    
    ; 
    
      //
    
    
      unlock account
    
    



    uEntry.Close();

}
  

Rename an Object

    
      public
    
    
      static
    
    
      void
    
     Rename(
    
      string
    
     objectDn, 
    
      string
    
     newName)

{

    DirectoryEntry child = 
    
      new
    
     DirectoryEntry(
    
      "
    
    
      LDAP://"
    
     + objectDn);

   child.Rename(
    
      "
    
    
      CN="
    
     + newName);

}
  

Active Driectory 操作(转来放起来,不要丢了)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论