Tuesday, May 17, 2011

The Power of PowerShell

Today I was faced with the challenge of creating an enterprise worth of Linked Mailboxes on Exchange 2010.  The Exchange server was sitting in a resource forest, adjacent to the production forest with two domains.  Linked mailboxes allow us to have a disabled User account in the resource forest, but grant authorization to the resource to a remote user account in a different trusted forest.  All this and more, just to migrate off of a previously unheard-of MTA.

I tested things out manually with a test mailbox, following Microsoft's article on the topic without any trouble.  Quickly noting the PowerShell example, I thought, "Hey, let's pipe in a list of user accounts from the production forest's Active Directory servers."

It was a great idea until:

[PS] C:\>Get-ADUser -Filter {Name -eq "Test"} -SearchBase "DC=contoso,DC=com" -Server ad01.contoso.com:3268
Get-ADUser : Unable to contact the server. This may be because this server does not exist, it is currently down, or it does not have the Active Directory Web Services running.

Uh oh.  Can I use a different cmdlet to connect to Server 2008 RTM?  Nope, not that I could find.  Active Directory Web Services was introduced with Windows Server 2008 R2.  So how about a different tool?  Remember CSVDE?  I had used it once before to perform a parallel Active Directory migration.  Not pretty, but it gets the job done.

A little hack here, and a little test there and viola:
csvde -f users.csv -d "OU=Users,DC=contoso,DC=com" -s AD01 -r "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))" -l "name,cn,sn,description,givenName,displayName,proxyAddresses,sAMAccountName,userPrincipalName"

Okay, I've got a CSV with some pretty useful information.  How do I loop through it with PowerShell to make those linked mailboxes?  A little searching through Technet, and I find J. Vosloo's article on a similar procedure for migrating mailboxes.  Import-CSV is a pretty powerful tool.  Now I can filter and purify my data in Excel, then run my script without any trouble.

$CSV = Import-CSV -path ".\users.csv"Foreach ($line in $CSV) {                $UPN = $line.sAMAccountName + "@resource.fabrikam.com"                $LMA = "CONTOSO\" + $line.sAMAccountName                New-Mailbox -Name $line.name -Alias $line.sAMAccountName -UserPrincipalName $UPN -SamAccountName $line.sAMAccountName -FirstName $line.givenName -Initials '' -LastName $line.sn -LinkedMasterAccount $LMA -LinkedDomainController 'ad01.contoso.com' }

And there we go!  All my mailboxes are created and linked.  There's more fun things you can do, like specify a particular OU for your target mailboxes based off of the OU of the originating Master Account, but that's left as an exercise to the reader.


  1. This is exactly what I am looking for. Thanks!!

    I have one problem though...
    When I run the command, I get this:
    Connecting to "unicdc01"
    "The connection cannot be established
    No log files were written. In order to generate a log file, please
    specify the log file path via the -j option."

    If I try with the -j option I'm told: "Unable to open log file"

    The trust is in place, so what's wrong here?


  2. It sounds like you aren't specifying an accessible path for csvde's -j option. Did you supply a valid path that can be accessed in the security context of the calling principal?