Use PowerShell to Get BIOS Information on Remote Servers


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to retrieve BIOS information from remote servers.

Hey, Scripting Guy! Question Hey, Scripting Guy! I really hope you can help me. I need to get a list of basic BIOS information from our servers. All of the servers that I need are listed in a single organizational unit (OU) in Active Directory. I am wondering if I can query that OU to get my servers, and then use Windows PowerShell to connect to those servers and query for BIOS information.

I tried using the Get-WmiObject cmdlet to query for the Win32_BIOS class in a few test scripts, but that did not work. When that didn’t work, I figured I was barking down the wrong path and gave up. But there are over a couple hundred servers in this OU, and although I can run the query locally, I don’t know why it won’t work remotely. I read your blog every day, and you always make this stuff seem so easy. Can you help me please? If I have to do this manually, I will be working until sometime next year on this project.

—CA

Hey, Scripting Guy! Answer Hello CA,

Microsoft Scripting Guy, Ed Wilson, is here. This morning it is rather cool here in Charlotte, North Carolina. I imagine it will warm up later, but right now it is pretty cool. That is fine, because I just got back from the gym, and am warmed up as it is. I am sitting on the porch with a nice cup of English Breakfast tea with a cinnamon stick and a bit of lemon grass. I decided to munch on an English muffin for my breakfast. The Scripting Wife brought back some homemade strawberry preserves from her visit to her mom, so I don’t want the stuff to go to waste. Anyway, I figure that after an hour in the gym, I can afford the muffin and jam.

CA, your problem is not all that difficult to solve, but I decided I would write a script to make it a bit easier to deal with. It breaks down into two parts. The first part is to query Active Directory Domain Services (AD DS) to retrieve the list of computers, and the second part is to use the list of computers to retrieve the WMI information.

Query AD DS

There are many ways of querying Active Directory to retrieve computer objects that happen to be in a specific organizational unit. To be honest, the method I use is pretty much dependent on what I start typing when I decide to make the query.

On my laptop, and in my test lab, I have the Active Directory module installed. This comes when I install the management tools for my particular operating system. I am running, Windows 8.1, so I downloaded my tool kit from the Microsoft Download Center: Remote Server Management Tools for Windows 8.1. There are also packages for other systems.

Because I have the RSAT tools installed, I can use the Active Directory module. I like to explicitly load a module when I know that I am going to use it, especially when I am writing a script. It makes things clearer, and is also a bit faster because Windows PowerShell does not have to figure out which module to load to gain access to a specific cmdlet. It is not much faster, but every second helps. The biggest advantage is from a readability standpoint. I will know that a specific cmdlet comes from a specific module.

First, I import the Active Directory module. Next, I create a hash table of values that I will use for my search parameters. I specify the server, the SearchBase, the SearchScope, and a very loose filter. I then use the hash table to pass the parameters to my Get-ADComputer cmdlet. This technique is called splatting, and it makes the script easy to read and easier to modify.

I then choose only the name parameter from the returned computer objects, and I store the results in the $servers variable. Here is the section of my script that returns all of the servers in my Servers organizational unit:

ipmo activedirectory

$SearchParameters = @{

'Server' = 'dc1.nwtraders.com'

'SearchBase' = 'ou=servers,dc=nwtraders,dc=com'

'SearchScope' = 'Subtree'

'Filter' = '*' }

 

$servers = (Get-ADComputer @SearchParameters).name

Make a CIM connection to the remote servers

Now that I have a list of all of my servers (stored in the $servers variable), I make a CIM connection to the remote servers.

Note  CA, one of the things you may have run in to when you were trying to use the Get-WmiObject cmdlet is that it uses DCOM, which is often blocked at the firewall level. Because the CIM cmdlets use standard Windows PowerShell remoting, and Windows PowerShell remoting is automatically turned on for servers (introduced in Windows Server 2012), I do not need to do anything special to make this work.

The New-CimSession accepts an array of computer names that it uses to create the new CIM sessions. I specify the SilentlyContinue error action because I do not want to be bothered with error messages about computers that may be turned off.

If I was concerned about recording this information, I could use the default value for the ErrorAction parameter, and then redirect my error messages to a file. Or I could use Try/Catch/Finally and record the name of servers that I am unable to reach. But for this operation, I just skip along.

I use the Get-CimInstance cmdlet, and I pass it to the array of CIM connections that I created in the previous command. I also specify that I want the Win32_Bios WMI class, and I select a specific number of properties from that class. These will appear in the output pane when I run the script. I could also redirect this information to a CSV file, which is what I would normally do.

Lastly, I remove the CIM sessions as part of my cleanup. Here is this portion of the script:

$CimConnection = New-CimSession -ComputerName $servers -ErrorAction SilentlyContinue

Get-CimInstance -CimSession $CimConnection -ClassName win32_bios |

Select SMBIOSBIOSVersion, Manufacturer, Name, SerialNumber, Version

Remove-CimSession -CimSession $CimConnection

The complete script is shown here:

ipmo activedirectory

$SearchParameters = @{

'Server' = 'dc1.nwtraders.com'

'SearchBase' = 'ou=servers,dc=nwtraders,dc=com'

'SearchScope' = 'Subtree'

'Filter' = '*' }

 

$servers = (Get-ADComputer @SearchParameters).name

$CimConnection = New-CimSession -ComputerName $servers -ErrorAction SilentlyContinue

Get-CimInstance -CimSession $CimConnection -ClassName win32_bios |

Select SMBIOSBIOSVersion, Manufacturer, Name, SerialNumber, Version

Remove-CimSession -CimSession $CimConnection

CA, that is all there is to querying AD DS to retrieve computer names, and then to query WMI information. Join me tomorrow when I will talk about more cool stuff.

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 

Comments (2)

  1. Valeras says:

    is this should be by design? 🙂
    like use @ instead of $ ?
    why i am getting error when using variable not hash table?

  2. Erik says:

    Is there any easy way to use something like this to get power plan settings for SQL servers? Recently found three of them running balanced and want to monitor and record.

Skip to main content