PowerShell - Pick a Domain Controller

2012, Feb 02    

I use a global variable to pick a Domain Controller so that I’m not constantly bouncing back and forth between Domain Controllers when running scripts. This helps to mitigate errors due to replication delays (normally, just a few seconds).

For Example, when you’re scripting and try to run Set-ADUser command followed immediately by a Get-ADUser command without specifying the -Server property as the same server for both commands, you may end up setting the change on one server and confirming the change was set (possibly a nano-second later) on a different server. This would lead to your confirmation to return as false.

To draw it out a little clearer … take the following command:

While ((Get-ADUser $SamAccountName -Properties HomeDrive).HomeDrive -eq $null) {
	Write-Host "Setting HomeDrive & Home Directory ..."
	Set-ADUser $SamAccountName -HomeDrive "H:" -HomeDirectory "\HOME-SERVERHOME$SamAccountName"
}
Write-Host "Moving on ..."

Without specifying -Server, the command might result in the following output:

Setting HomeDrive & Home Directory ...
Setting HomeDrive & Home Directory ...
Setting HomeDrive & Home Directory ...
Setting HomeDrive & Home Directory ...
Moving on ...

If I do specify -Server, as shown:

While ((Get-ADUser $SamAccountName -Server $myDC -Properties HomeDrive).HomeDrive -eq $null) {
	Write-Host "Setting HomeDrive & Home Directory ..."
	Set-ADUser $SamAccountName -Server $myDC -HomeDrive "H:" -HomeDirectory "\HOME-SERVERHOME$SamAccountName"
}
Write-Host "Moving on ..."

I get the following output, everytime:

Setting HomeDrive & Home Directory ...
Moving on ...

I set $myDC in my $Profile with a global variable and calling the Set-DC function I’ve written below.

[string] $global:myDC = ""
Set-myDC
Write-Debug "myDC:  $myDC"

Of course, you could just set the $myDC statically, but what fun is that? Here’s my solution:

<#
.SYNOPSIS
Sets the myDC global variable.
.DESCRIPTION
Gets a list of domain controllers and takes one from the list.
.PARAMETER Return
If set, will return the FQDN of a DC, other than the globally set DC, intead of setting it globally.  Useful for targetting another DC without changing the globally used DC.
.INPUTS
.OUTPUTS
Sets $global:CASITS_UNTDC discovered FQDN.
If -Return is used, $global:myDC is not set and the discovered FQDN is returned as a string.
.EXAMPLE
Set-myDC
.EXAMPLE
$myDC = Set-myDC -Return
.NOTES
.LINK
go.vertigion.com/PowerShell-Set-myDC
#>
function Set-myDC
{
	param(
        [Parameter(
			HelpMessage = "If set, will return the result intead of setting globally."
		)]
        [switch] $Return
    )
	
	$DCList = $null
	while ($DCList -eq $null) {
		$DCList = Get-ADDomainController -Filter * | Select HostName
	}
	if ($Return.isPresent) {
		$DC = ''
		while ($DC -eq $myDC) {
			$DC = $DCList[$(Get-Random -Minimum 0 -Maximum ($DCList | Measure-Object).Count)].HostName
		}
		return $DC
	} else {
		$global:myDC = $DCList[$(Get-Random -Minimum 0 -Maximum ($DCList | Measure-Object).Count)].HostName
	}
}

Hope it helps others out there. Just add the function to your PowerShell Profile or as a Functions in a script to make it available!