There’s a group of servers that I use for a specific project. I can never remember their names or how those correspond to their roles (web front end vs. data back end). Although I’ve updated their Active Directory (AD) descriptions, and created two, specifically named AD groups for them, I wanted an even quicker way to remind myself whose who. With that in mind, I updated my profile with a custom variable that is an array, of arrays.
In this Quick Learn, we’ll work with an example that actually uses three groups of roles — our DCs, our web servers, and our SQL servers. As you’ll soon see, our servers are named after Santa Claus’ reindeer. These names have nothing to do with the role of these servers, and since their names are all closely related, it’s difficult to remember who does what.
This first example, below, demonstrates how we create a new variable, or modify an already existing variable. When we echo the contents of our variable, we get all the computer names, regardless of what array they are in, within the base array. The term ‘base array’ is probably not something you’ll hear or read about outside this post. It’s being used here to help distinguish the array that holds all the other arrays — the container array.
PS C:\> Set-Variable -Name Computers -Value @(('dasher','vixen','cupid'),('comet','dancer','donner'),('blitzen','rudolph','prancer'))
PS C:\> $Computers
dasher
vixen
cupid
comet
dancer
donner
blitzen
rudolph
prancer
We can use an index to return one of the arrays within the base array. In the examples below, you can see how each can be accessed. This is probably a good time to review indexes: The first item in an array is index zero, the second item is index one, the third item is index two, and so on.
PS C:\> $Computers[0]
dasher
vixen
cupid
PS C:\> $Computers[1]
comet
dancer
donner
PS C:\> $Computers[2]
blitzen
rudolph
prancer
In the following example, we can use two indexes to access a specific server. The first index represents which array (within the base array) I want to return, like it did above, and the second index indicates which server I want to return.
PS C:\> $Computers[0][2]
cupid
PS C:\> $Computers[1][0]
comet
PS C:\> $Computers[2][1]
rudolph
The difficult part is going to be able to remember which index is for the DCs, the web servers, or the SQL servers. In that case, I’ll create three more variables to use in place of those index integers.
PS C:\> Set-Variable -Name DCs -Value 0
PS C:\> Set-Variable -Name Web -Value 1
PS C:\> Set-Variable -Name SQL -Value 2
PS C:\> $DCs,$Web,$SQL
0
1
2
With the combination of my $Computers variable and the three, role-specific variables, I am able to easily return the set of servers I want.
PS C:\> $Computers[$DCs]
dasher
vixen
cupid
PS C:\> $Computers[$Web]
comet
dancer
donner
PS C:\> $Computers[$SQL]
blitzen
rudolph
prancer
Now that we have this all figured out, I can use them in different commands. Here’s a couple examples:
PS C:\> $Computers[$SQL] | ForEach-Object {Test-Connection $_ -Count 1}
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
TOMMYMS PC... blitzen 10.10.10.80 32 1
TOMMYMS PC... rudolph 10.10.10.81 32 1
TOMMYMS PC... prancer 10.10.10.82 32 1
PS C:\> Get-Service -ComputerName ($Computers[$DCs]) -Name *bit* | Select-Object MachineName,Name,Status | Format-Table -AutoSize
MachineName Name Status
----------- ---- ------
dasher BITS Stopped
vixen BITS Running
cupid BITS Stopped
The unfortunate thing about hard coding computer names in our profile, is that we’ll run into problems when new servers are added and old ones are decommissioned. Therefore, we’re going to use AD groups — something I mentioned earlier — to populate our array variable. We’ll pull our DCs from the Domain Controllers, and our web servers and SQL servers from two fictions AD groups: WebServers and SQLBoxes. Here’s the command we’ll add to our profile to ensure we always have the correct server names. While this can all be on a single line command I’ve added line breaks to give it an easier-to-read appearance.
Set-Variable -Name Computers -Value @(
((Get-ADDomainController -Filter *).Name),
((Get-ADGroupMember -Identity WebServers).Name),
((Get-ADGroupMember -Identity SQLBoxes).Name)
)
And, that’s it. If for some reason you’re using PowerShell 2.0 or lower (and I really hope you’re not), you’ll need to include Import-Module -Name ActiveDirectory in your profile. As well — and it should go without saying — you’ll need to be working from a computer that actually has the ActiveDirectory module installed. Although I’m using PowerShell 4.0, I still include Import-Module -Name ActiveDirectory in my profile, so I don’t have to wait for it to auto load, when I run my first AD cmdlet.