Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to do a hardware inventory of domain controllers needing an upgrade.

Microsoft Scripting Guy, Ed Wilson, is here. Wow, it seems like a major holiday. The Scripting Wife ordered me some organic spearmint, licorice root, and orange peel from my favorite spice house. I just made myself a pot of tea with a pinch of orange peel, licorice root, English breakfast tea, lemon grass, hibiscus flower, and crushed cinnamon stick. Dude, the stuff is good. Along with just about a half a spoonful of local honey—my Scripting Guys special blend will really wake you up in the morning. Not that I need any waking up today, because I am anxious to get started on writing my script to survey my domain controller hardware in preparation for my domain functional level and forest functional level upgrade.

Note   This is the second part of a series of posts where I talk about upgrading domain and forest functional levels to Windows Server 2012. You really should read yesterday’s post, Use PowerShell to Prepare for a Domain Upgrade, before you are too carried away with today’s post. This is because I am picking up directly with yesterday’s post.

It is just a little bit of WMI

Well, yesterday I talked about querying for domain controllers and returning their current operating system version. If the servers are running Windows Server 2012, there is no need to do a hardware inventory because they are already upgraded. If not, then I need to obtain the hardware info, so I can plan the upgrade. Here is the code I use to determine the operating system version and to decide whether I want to do the WMI query.

Import-Module ActiveDirectory

$dc = Get-ADComputer -SearchBase "ou=domain controllers,dc=iammred,dc=net" -Filter * `

    -Properties operatingsystem

Foreach ($cn in $dc)

 {

  If ($cn.operatingsystem -notmatch '2012')

Now, if the operating system is not Windows Server 2012, I need to query a bunch of WMI classes. This is pretty boring stuff here. I use the Get-WMiObject cmdlet to do the query, and I query five different WMI classes: Win32_Bios, Win32_OperatingSystem, Win32_Processor, Win32_PhysicalMemory, and Win32_Volume. I store each returned object in appropriately named variables. Here is that section of the script.

     $bios = Get-WmiObject -Class win32_bios -ComputerName $cn.name

     $os = Get-WmiObject -class win32_operatingsystem -ComputerName $cn.name

     $processor = Get-WmiObject -Class win32_Processor -ComputerName $cn.name

     $memory = Get-WmiObject -Class win32_physicalmemory -ComputerName $cn.name

     $volume = Get-WmiObject -Class win32_volume -ComputerName $cn.name

Create and return a nice custom object

Ok, so the WMI queries are not too exciting but creating an appropriate custom object is a bit more exciting. I use the New-Object cmdlet to create a custom psobject. I specify the –Property parameter to create the properties on the newly created object. One object for each found domain controller creates. I run each WMI query against my local computer and examine the output. I then select the most useful (for me) properties from each WMI class, and this is what I store in the object. Here is the applicable portion of the script.

         New-Object -TypeName psobject -Property @{

         ComputerName = $cn.DistinguishedName

         biosVersion = $bios.SMBIOSBIOSVersion

         biosMaker = $bios.Manufacturer

         osArchitecture = $os.OSArchitecture

         osName = $os.Caption

         osServicePack = $os.ServicePackMajorVersion

         ProcessorAdddressWidth = $processor.AddressWidth

         ProcessorClock = $processor.MaxClockSpeed

         ProcessorCores = $processor.NumberOfCores

         ProcessorLogical = $processor.NumberOfLogicalProcessors

         ProcessorMake = $processor.Manufacturer

         MemoryCapacity = $memory.capacity

         MemoryBank = $memory.DeviceLocator

         VolumeLetter = $volume.driveLetter

         VolmeFreeSpace = $volume.freespace

         VolumeCapacity = $volume.Capacity }

You know what? This is it. The script uses the technique from yesterday to find all domain controllers and uses Get-WmiObject to query WMI and New-Object to create the custom object. Not too bad.

The following image shows sample output from the script.

Image of command output

To make the script easy for you to use and to modify, I have uploaded it to the Scripting Guys Repository. You can download it from there.

Well, that is all there is to querying Active Directory for domain controllers and performing a hardware inventory. Join me tomorrow when Windows PowerShell MVP and Honorary Scripting Guy Richard Siddaway will return with another installment of his most excellent Windows PowerShell workflow series.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy