| Richard's profileRichard Siddaway's BlogPhotosBlogLists | Help |
|
February 19 Accessing AD with PowerShellWith the introduction of Windows 2000 and Active Directory seven years ago Microsoft began a process of increasing the emphasis placed on the command line for administration. There are many tasks that it is more convenient to perform from the command line when administering Active Directory. Microsoft has introduced a set of command line tools dsquery etc. specifically for querying and modifying Active Directory. These tools enable the commonest tasks to be performed but for real low level access to the Active Directory the recommended approach for administrators has been via scripting – using VBScript. The examples in the various books that have been produced since 2000 and the collection of scripts on the TechNet script center practically all use VBScript. The following script can be used to create an OU Set objDomain = GetObject("LDAP://dc=manticore,dc=org") Set objOU = objDomain.Create("organizationalUnit", "ou=Sphinx") objOU.SetInfo The first line creates an ADSI object bound to the Active Directory domain. The second line creates the OU and the third line performs the action that actually creates a permanent instance of the object in the Active Directory. Until SetInfo is called the object is not actually created. ADSI is short for Active Directory Services Interface. It is a COM object that can be used through any programming language that can instantiate a COM object. The ADSI SDK can be accessed online at http://msdn2.microsoft.com/en-us/library/aa772170.aspx. ADSI can be used to access other directory stores including:
With the introduction of PowerShell that leaves us the question of how do we access Active Directory with PowerShell. At the moment there are three main ways of achieving this goal.
This is all a little confusing especially for a beginner to PowerShell or someone who is not familiar with the .NET framework. I will provide examples of how these various options are used. In order to demonstrate how all of these options are used we need to change to creating a site object. The System.DirectoryServices.ActiveDirectory Namespace only supports a subset of the Active Directory objects as it is intended to be used for the administration of Active Directory rather than accessing data. The following VBScript to create a site will be used as a reference in the discussion. ' get sites container set objRootDSE = GetObject("LDAP://RootDSE") set objSitesCont = GetObject("LDAP://cn=sites," & objRootDSE.Get("configurationNamingContext")) 'Create site set objSite = objSitesCont.Create("site","cn=MyNewSite") objSite.SetInfo 'Create licensing site settings object set objLicensing = objSite.Create("licensingSiteSettings", "cn=Licensing Site Settings") objLicensing.SetInfo 'Create NTDS Site Settings object set objNTDS = objSite.Create("nTDSSiteSettings", "cn=NTDS Site Settings") objNTDS.SetInfo 'Create servers container set objServersCont = objSite.Create("serversContainer", "cn=Servers") objServersCont.SetInfo
If we start by using the [ADSI] constructor we end up with the following script. # get sites container $Root = [ADSI]"LDAP://RootDSE" $SitesCont = [ADSI]("LDAP://cn=sites," + $Root.Get("configurationNamingContext")) #Create site $Site = $SitesCont.Create("site","cn=MyNewSite2") $Site.SetInfo() #Create licensing site settings object $Licensing = $Site.Create("licensingSiteSettings", "cn=Licensing Site Settings") $Licensing.SetInfo() #Create NTDS Site Settings object $NTDS = $Site.Create("nTDSSiteSettings", "cn=NTDS Site Settings") $NTDS.SetInfo() #Create servers container $ServersCont = $Site.Create("serversContainer", "cn=Servers") $ServersCont.SetInfo()
Notice how the methods and syntax are so similar to the VBScript version. This is by design and allows a fairly straight forward method of migrating from using VBScript to access Active Directory to using PowerShell. The [ADSI] construction in effect gives the effect as Get-Object in VBScript. There is one major issue with using this approach if you create the $Site object for instance and perform a get-member on it the methods and properties such as SetInfo that you accessed through VBScript do NOT show. Get-member returns $site as a directory entry object and shows the .NET methods and properties as discussed below. The COM type methods accessed through VBScript are effectively hidden and need referencing via the ADSI documentation. The next stage is to look at using the .NET System.DirectoryServices Namespace which is a .NET wrapper for ADSI. We can take our script and rewrite it to give the following code. # get sites container $Root = [System.DirectoryServices.DirectoryEntry] "LDAP://RootDSE" $SitesCont = [System.DirectoryServices.DirectoryEntry]("LDAP://cn=sites," + $Root.Get("configurationNamingContext")) #Create site $Site = $SitesCont.Create("site","cn=MyNewSite3") $Site.psbase.CommitChanges() #Create licensing site settings object $Licensing = $Site.Create("licensingSiteSettings", "cn=Licensing Site Settings") $Licensing.psbase.CommitChanges() #Create NTDS Site Settings object $NTDS = $Site.Create("nTDSSiteSettings", "cn=NTDS Site Settings") $NTDS.psbase.CommitChanges() #Create servers container $ServersCont = $Site.Create("serversContainer", "cn=Servers") $ServersCont.psbase.CommitChanges()
The major changes here are that we use [System.DirectoryServices.DirectoryEntry] instead of [ADSI] and that we use CommitChanges() instead of SetInfo(). Note that the .NET method CommitChanges() is just a wrapper for the COM SetInfo method. The other thing to notice is the use of psbase in the lines that call CommitChanges(). A PowerShell object is not always a pure .NET object and will often have a PowerShell created wrapper around it. If you put the latest version of our site creation code in a script and run it as . ./script.ps1 i.e. dot source it so that it runs in the same context as your main PowerShell process you will find that the objects used within the script are still available. Try the following commands $Site | get-member $Site.psbase | get-member The first command will return the properties of the Active Directory object referenced by $Site whereas the second returns the methods and properties of the .NET object $Site. More on PowerShell objects and their properties another time. In order to access the .NET methods and properties we need to use psbase to reference the base object. The third and final method of accessing Active Directory is by using System.DirectoryServices.ActiveDirectory which will make life a lot easier for us but does not provide everything we need as it is intended for administering Active Directory not the data held within Active Directory. ## get current forest and set context $for = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() $fortyp = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]"forest" $forcntxt = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($fortyp, $for) ## create the site $site = new-object System.DirectoryServices.ActiveDirectory.ActiveDirectorySite($forcntxt, "MyNewSite4") $site.Save() By using this approach we can greatly simplify some administrative tasks. For some of its tasks System.DirectoryServices.ActiveDirectory will bypass ADSI and use other APIs which gives in effect a .NET approach to manipulating Active Directory. By getting a direct reference to the forest and its context we are performing the same steps as in earlier code where we bind to RootDSE and the configurationNamingContext. It is then a simple matter to create the site and save the object back to Active Directory. Note that the associated Servers, NTDS and Licensing objects are all created automatically. We have seen how to use PowerShell to access Active Directory. Until we have a set of cmdlets for accessing and manipulating Active Directory similar to those available for Exchange 2007 we need to code our scripts using one of the methods described above. All three methods will work – it is really a matter of picking the one that you feel comfortable with and hopefully making the best use of the available options. Trackbacks (1)The trackback URL for this entry is: http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!241.trak Weblogs that reference this entry
|
|
|