Saturday, March 7, 2009

Using PowerShell and S.DS.AD to create Sites and Service objects

System.DirectoryServices.ActiveDirectory (S.DS.AD) is a .NET namespace available for performing common tasks related to Active Directory Domain Services. S.DS.AD differs from S.DS in that it is a pure .NET interface which allows us to extend deeper into DS development. See S.DS.AD Scenarios here.

With PowerShell (PSH), we can leverage the classes in this namespace for common manual tasks that can be scripted. For example, in a migration scenario, managing AD sites and services can be time consuming to set up. Here are some functions I wrote which allow you to automate these process using PSH.

To do bulk creations of site objects, you would store your configuration in a CSV file and use them as parameters to each PSH function.

Say we need to 1. Create Sites, 2. Create Subnets, 3. Create SiteLinks, and 4. Configure our SiteLinks. Using Excel, you can create 4 CSV source files for each task, then use the Import-CSV and ForEach-Object cmdlets to call each function for each record.

For example:

Import-Csv C:\importFile.csv ForEach-Object {Create-Site $_.SiteName}
Import-Csv C:\importSubnets.txt ForEach-Object {Create-SubNet $_.SubNet $_.SiteName}
Import-Csv C:\importSiteLinks.txt ForEach-Object {Create-SiteLink $_.SiteLinkName $_.Site $_.Cost $_.Interval}

Here are the PSH functions:

Creating AD Sites

Function Create-Site{Param ($siteName)
$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$type = [System.DirectoryServices.ActiveDirectory.DirectoryContextType]"forest"
$contextType = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext($type,$forest)
$site = New-Object System.DirectoryServices.ActiveDirectory.ActiveDirectorySite($contextType,$siteName)
$site.Options = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteOptions]::GroupMembershipCachingEnabled
$site.Save()
Write-Host "Creating site object $siteName..." }

Creating AD Subnets

Function Create-SubNet{Param($subNetName,$siteName)
$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$type = [System.DirectoryServices.ActiveDirectory.DirectoryContextType]"forest"
$contextType = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext($type,$forest)
$site = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($contextType, $siteName)
$subnet = New-Object System.DirectoryServices.ActiveDirectory.ActiveDirectorySubnet($contextType,$subNetName,$site)
$subnet.Save()
Write-Host "Creating subnet object $subNetName..." }

Creating AD SiteLinks

Function Create-SiteLink{Param($siteLinkName,$siteName,$siteCost,$repInterval)
$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$type = [System.DirectoryServices.ActiveDirectory.DirectoryContextType]"forest"
$contextType = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext($type,$forest)
$trans = [System.DirectoryServices.ActiveDirectory.ActiveDirectoryTransportType]::Rpc
$site = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($contextType,$siteName)
$link = New-Object System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteLink($contextType,$siteLinkName,$trans)
$link.Cost = $siteCost
$link.ReplicationInterval = $repInterval
$d = $link.Sites.Add($site)
$link.Save()
Write-Host "Creating siteLink object $siteLinkName..." }

Adding Sites to a SiteLink

Function Add-SitetoSiteLink{Param($siteName,$siteLinkName)
$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$type = [System.DirectoryServices.ActiveDirectory.DirectoryContextType]"forest"
$contextType = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext($type,$forest)
$site = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($contextType,$siteName)
$link = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteLink]::FindByName($contextTye,$siteLinkName)
$link.Sites.Add($site)
$link.Save() }

Wednesday, December 17, 2008

Installing ADAM on Vista SP1

To date, Microsoft still hasn’t released an ADAM build for Vista. We’ve since had to hack our way to get ADAM installed; however, the release of Vista SP1 presented a new set of obstacles. Basically what you’ll see is an “Entry Point Not Found” error which references the VSSAPI.DLL. In order to overcome this, you just copy the older version of the VSSAPI.DLL into the ADAM directory on your Vista machine (Thanks siudyda.com for the post).

Here are the steps to get ADAM installed on an Vista SP1 build:

  1. Install ADAM on a non-Vista machine.
  2. Copy the %WINDIR%\ADAM folder from your non-Vista machine to the same location on your Vista machine.
  3. Create a new registry key HKLM\Software\Microsoft\Windows\CurrentVersion\ADAM_Shared. Under this key, create a new Multi-String value named “SharedFolders”.
  4. Run the adaminstall.exe from the %WINDIR%\ADAM directory. Do not import any LDIF files. Note: if you experience the error mentioned above, just copy the older version of VSSAPI.DLL into your ADAM directory.
  5. Complete the wizard and you should have a fully functional ADAM instance. All you need to do is import the LDIF files you want to design your schema.

Saturday, October 4, 2008

Invalid DN Syntax when creating new object classes in ADAM

When recreating an ADAM directory for a project that uses custom object classes, I ran into a problem attempting to import my schema using Ldifde.exe using the following command line:

“ldifde -i -u -f export_prod_schema.ldf -s server:port -b username domain password -j . -c "cn=Configuration,dc=X" #configurationNamingContext”

Below is the error my logfile reported:

-

Entry DN: cn=xxxxx,cn=Schema,#configurationNamingContext

Add error on line 15: Invalid DN Syntax

The server side error is "The object name has bad syntax."

An error has occurred in the program

-

The problem was actually in Ldifde.exe itself. Apparently, the version of Ldifde.exe from the system32 directory does not support #macros. You have to use the version provided with the ADAM (%windir%\ADAM) installation.

Thanks to Dmitri Garilov for posting this in the news group.

Wednesday, September 24, 2008

Reminder: C# character escape sequences

C# defines the following character escape sequences:

  • \' - single quote, needed for character literals
  • \" - double quote, needed for string literals
  • \\ - backslash
  • \0 - Unicode character 0
  • \a - Alert (character 7)
  • \b - Backspace (character 8)
  • \f - Form feed (character 12)
  • \n - New line (character 10)
  • \r - Carriage return (character 13)
  • \t - Horizontal tab (character 9)
  • \v - Vertical quote (character 11)
  • \uxxxx - Unicode escape sequence for character with hex value xxxx
  • \xn[n][n][n] - Unicode escape sequence for character with hex value nnnn (variable length version of \uxxxx)
  • \Uxxxxxxxx - Unicode escape sequence for character with hex value xxxxxxxx (for generating surrogates)

Of these, \a, \f, \v, \x and \U are rarely used in my experience.

link to original post