{"id":4209,"date":"2013-02-05T00:01:00","date_gmt":"2013-02-05T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2013\/02\/05\/use-powershell-to-obtain-domain-controller-hardware-info\/"},"modified":"2013-02-05T00:01:00","modified_gmt":"2013-02-05T00:01:00","slug":"use-powershell-to-obtain-domain-controller-hardware-info","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-obtain-domain-controller-hardware-info\/","title":{"rendered":"Use PowerShell to Obtain Domain Controller Hardware Info"},"content":{"rendered":"<p><strong style=\"font-size: 12px\">Summary:<\/strong><span style=\"font-size: 12px\"> Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to do a hardware inventory of domain controllers needing an upgrade.<\/span><\/p>\n<p>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&mdash;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.<\/p>\n<p style=\"padding-left: 30px\"><strong>Note<\/strong>&nbsp;&nbsp; This is the second part of a series of posts where I talk about upgrading domain and forest functional levels to Windows Server&nbsp;2012. You really should read yesterday&rsquo;s post, <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2013\/02\/04\/use-powershell-to-prepare-for-a-domain-upgrade.aspx\" target=\"_blank\">Use PowerShell to Prepare for a Domain Upgrade<\/a><em>, <\/em>before you are too carried away with today&rsquo;s post. This is because I am picking up directly with yesterday&rsquo;s post.<\/p>\n<h2>It is just a little bit of WMI<\/h2>\n<p>Well, yesterday I talked about querying for domain controllers and returning their current operating system version. If the servers are running Windows Server&nbsp;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.<\/p>\n<p style=\"padding-left: 30px\">Import-Module ActiveDirectory<\/p>\n<p style=\"padding-left: 30px\">$dc = Get-ADComputer -SearchBase &#8220;ou=domain controllers,dc=iammred,dc=net&#8221; -Filter * `<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; -Properties operatingsystem<\/p>\n<p style=\"padding-left: 30px\">Foreach ($cn in $dc)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;{<\/p>\n<p style=\"padding-left: 30px\">&nbsp; If ($cn.operatingsystem -notmatch &#8216;2012&#8217;)<\/p>\n<p>Now, if the operating system is not Windows Server&nbsp;2012, I need to query a bunch of WMI classes. This is pretty boring stuff here. I use the <strong>Get-WMiObject<\/strong> cmdlet to do the query, and I query five different WMI classes: <strong>Win32_Bios<\/strong>, <strong>Win32_OperatingSystem<\/strong>, <strong>Win32_Processor<\/strong>, <strong>Win32_PhysicalMemory<\/strong>, and <strong>Win32_Volume<\/strong>. I store each returned object in appropriately named variables. Here is that section of the script.<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $bios = Get-WmiObject -Class win32_bios -ComputerName $cn.name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $os = Get-WmiObject -class win32_operatingsystem -ComputerName $cn.name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $processor = Get-WmiObject -Class win32_Processor -ComputerName $cn.name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $memory = Get-WmiObject -Class win32_physicalmemory -ComputerName $cn.name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $volume = Get-WmiObject -Class win32_volume -ComputerName $cn.name<\/p>\n<h2>Create and return a nice custom object<\/h2>\n<p>Ok, so the WMI queries are not too exciting but creating an appropriate custom object is a bit more exciting. I use the <strong>New-Object<\/strong> cmdlet to create a custom psobject. I specify the <strong>&ndash;Property<\/strong> 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.<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; New-Object -TypeName psobject -Property @{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ComputerName = $cn.DistinguishedName<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; biosVersion = $bios.SMBIOSBIOSVersion<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; biosMaker = $bios.Manufacturer<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osArchitecture = $os.OSArchitecture<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osName = $os.Caption<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osServicePack = $os.ServicePackMajorVersion<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessorAdddressWidth = $processor.AddressWidth<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessorClock = $processor.MaxClockSpeed<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessorCores = $processor.NumberOfCores<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessorLogical = $processor.NumberOfLogicalProcessors<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessorMake = $processor.Manufacturer<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemoryCapacity = $memory.capacity<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemoryBank = $memory.DeviceLocator<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VolumeLetter = $volume.driveLetter<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VolmeFreeSpace = $volume.freespace<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VolumeCapacity = $volume.Capacity }<\/p>\n<p>You know what? This is it. The script uses the technique from yesterday to find all domain controllers and uses <strong>Get-WmiObject<\/strong> to query WMI and <strong>New-Object<\/strong> to create the custom object. Not too bad.<\/p>\n<p>The following image shows sample output from the script.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8461.hsg-2-5-13-01.png\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8461.hsg-2-5-13-01.png\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>To make the script easy for you to use and to modify, I have <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Query-AD-DS-for-domain-9c89feef\" target=\"_blank\">uploaded it to the Scripting Guys Repository<\/a>. You can download it from there.<\/p>\n<p>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.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><strong>Ed Wilson, Microsoft Scripting Guy<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3,45],"class_list":["post-4209","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4209","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=4209"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4209\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=4209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=4209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=4209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}