How to inventory server hardware with PowerShell


Most of us have had to deal with hardware that stays in service well beyond its intended end-of-life date, or that, for budget and bureaucratic reasons, doesn’t even go into service until the end of its life. end of its life.

The first step in planning and prioritizing server hardware upgrades is to inventory and assess your existing hardware, which might seem like an appropriate job for an IT intern, it’s also a perfect job for PowerShell.

Read system telemetry with PowerShell

The main PowerShell cmdlet throughout this discussion is Get-WmiObject. Most server administrators will have at least a passable knowledge of Windows Management Interface (WMI), a set of telemetry points to help monitor server performance and health, among other things. WMI is frequently used to filter the application of GPOs only to computers that meet a specific set of criteria. WMI is Microsoft’s implementation of the Common Information Model (CIM), which is an industry standard. The Get-WmiObject The cmdlet can access the WMI and CIM classes.

PowerShell also offers the Get-CimInstance cmdlet, which is functionally similar to Get-WmiObject but with a few key differences. Specifically, Get-WmiObject uses Distributed Component Object Model (DCOM) to communicate with remote computers, while Get-CimInstance uses PowerShell Remoting / Windows Remote Management (WinRM). There are some technical differences in terms of protocols, but the main functional difference is that WinRM requires some configuration on the remote computer.

Often the hardest part of using WMI is finding the right class to use. Functioning Get-WmiObject with the -List parameter will return over a thousand classes to choose from, but to limit that to less than 25 you can use this:

Get-WmiObject -List | Where-Object Name -like *processor*.

A nice advantage of Get-WmiObject is that the -ComputerName parameter accepts multiple host names, which means that you can easily extract information from a list of systems with very little effort. This could be a hard-coded list of host names, a selection from a text file, or a list of computer names taken from Active Directory.

Get server processor details

The CIM_Processor class can provide information about the processor, but as with many other PowerShell cmdlets, Get-WmiObject is not super available by default. Execute the command

Get-WmiObject CIM_Processor

returns half a dozen details like in this screenshot (click to enlarge):

01 basic processor information Tim ferrill

Fortunately, collecting additional information from the cmdlet is trivial by leveraging the Select-Object cmdlet.

The Get-WmiObject CIM_Processor | Select-Object * command takes the output of Get-WmiObject, even fields that do not display automatically, and returns the full set. For practical use, it’s probably more information than what’s really useful, so use that as a starting point and narrow things down to the specific areas that you’re really interested in.

Some key processor performance metrics are universal (clock speed, number of cores or threads, cache details), regardless of manufacturer, family, or even processor architecture. WMI allows access to each of these values, which makes them accessible by programming using Get-WmiObject. Additionally, servers often have multiple processors, which makes socket identification – the physical location of the processor on the motherboard – key information.

Here’s what a command looks like to list a specific set of details for server processors:

Get-WmiObject CIM_Processor | Select-Object PSComputerName, Name, DeviceID, SocketDesignation, ProcessorType, MaxClockSpeed, NumberOfCores, ThreadCount, L2CacheSize, VirtualizationFirmwareEnabled

System memory detail

The steps for reading details from system memory are similar to reading information from the processor, although memory is still more likely to have multiple hardware components. Even entry-level servers with a single processor can potentially have multiple memory modules. This is not necessarily critical when fetching details from a single server, but can become important when performing a mass inventory and you want that information to be stored or displayed in a way. particular. For example, if your intention is to have a spreadsheet that you can analyze, do you want to view details for each memory module or summary data for system memory as a whole?

If you use the techniques above and extract a list of WMI classes with “memory” in the name, you will see several possible candidates, but CIM_PhysicalMemory is the best choice at this time. You might be interested in CIM_Memory and CIM_AssociatedProcessorMemory later, as both of these go into the processor cache. In terms of the initial extraction of details from system memory, let’s go ahead and assume that you have already extracted a list of all the details available from the CIM_PhysicalMemory class using something that looks like the following command:

Get-WmiObject CIM_PhysicalMemory | Select-Object BankLabel, Manufacturer, PartNumber, SerialNumber, Capacity, Speed, ConfiguredClockSpeed, ConfiguredVoltage

As with the processor details we extracted earlier, this provides a list of benchmark details commonly used to define system memory performance capabilities. This list is certainly not exhaustive and can be adapted to your needs quite easily.

Now, if a list of each memory module meets your inventory needs, then great, you’re pretty much done. But just for fun, let’s say you prefer to have a summary of system memory, capturing only the overall capacity and number of physical memory modules contained in your server. For this we can use the Measure-Object cmdlet to both count the number of physical memory devices and calculate the total sum of capacity:

$ramSummary = Get-WmiObject CIM_PhysicalMemory | Select-Object -ExpandProperty Capacity | Measure-Object -Sum

As you can see, we are attributing the results of this command primarily to a variable, a unit of memory to store the values, in this case $ ramSummary. So, we can easily get both number and sum after running the command. We have already spoken of both the Get-WmiObject and Select-Object cmdlets, although the -ExpandProperty parameter isn’t something we’ve covered before. As shown below (click to expand), -ExpandProperty converts the result of an object with a name displayed as the column header (in this case Capacity) and values, into a simple list of values ​​(in this case 8589934592).

02 memory and expandproperty Tim ferrill

For the purposes of this exercise, this is essential because we introduce the list of values ​​into the Measure-Object cmdlet. Note that Measure-Object provides a count by default, this detail is implied, but we need to specify that we also want a sum. Additional flags can be specified to retrieve an average, maximum, minimum, or other metrics (potentially depending on the type of information entered into the cmdlet).

Since we have defined the variable $ ramSummary, we can access the number and the sum as properties of the variable: $ ramSummary.Count and $ ramSummary.Sum. The unit of measure initially returned by the CIM_PhysicalMemory class for memory capacity is bytes, so it’s very likely that you want to display a value as something a little more readable. There are several ways to do this, just dividing the result by 1024 three times will get you gigabytes, but a more elegant way is to use PowerShell constants to just convert the number to gigabytes using something like $ ramSummary.Sum / 1 GB.

TPM information for security

Security is an important factor in modern networks, especially as virtual machines and containers increase system density. Trusted Platform Modules (TPMs) are key to Windows security capabilities like BitLocker Disk Encryption. Like Windows 11, installing Windows Server 2022 will require a TPM 2.0 chip.

Of course, there’s a WMI class that you can use to retrieve TPM-related information, but there’s also a dedicated cmdlet that lets you do more than just check uptime and status. Let’s start with the WMI Win32_TPM class.

If you retrieve a list of WMI objects using the -List Win32_TPM parameter, the WMI class is not displayed, and if you try Get-WmiObject Win32_TPM this will give you an error indicating that the class is invalid. This is because you need to specify the namespace or path where the class exists:

Get-WmiObject -Namespace root/cimv2/security/microsofttpm -Class Win32_TPM

It’s certainly more complicated than just providing the class name, but it gets the job done. Note: To use the Win32_TPM class, you need administrative credentials.

WMI is not just a read-only system; there are methods (programming functions) that can be executed on WMI objects. This has limited hardware benefits, but is more useful with things like system processes or services.

There are a few methods with the Win32_TPM class that are particularly useful to know about, but first here’s how to extract a list of available methods for the class:

$tpm = Get-WmiObject -Namespace root/cimv2/security/microsofttpm -Class Win32_TPM
$tpm | Get-Member -MemberType Method

Get-Member is one of those cmdlets with Acquire help which can be useful almost daily. This pair of commands first stores the output of the WMI class in the $ tpm variable, and then lists the methods associated with that class. Some potentially useful methods in the Win32_TPM class are IsActivated (), IsEnabled (), and SelfTest (); each of which can be executed by referencing the variable followed by the method like: $ tpm.SelfTest ().

As mentioned earlier, there is a set of dedicated TPM cmdlets, and you can get the list using Get-Command -Noun Tpm, and here’s something to note about one of them. If you run Get-RPM you’ll probably notice right away that there is some overlap with the WMI-based details we worked on. Obviously Get-RPM is much faster to type than the full WMI command, but the main downside is that there is no -ComputerName parameter like there is with Get-WmiObjecttherefore running on remote systems is more difficult.

Check the warranty status

Depending on your server hardware manufacturer, it may be possible to verify its warranty status programmatically, assuming your hardware vendor supports it. If you’re using one of the big vendors like HPE, Dell, or Lenovo, there’s a good chance there’s an API available, and even a PowerShell package available in the PowerShell gallery. In most cases, you will need to be able to pass your system’s serial number (aka service tag) to the module, which you can get by using the SerialNumber property in the Win32_Bios class:

Get-WmiObject Win32_Bios | Select-Object -ExpandProperty Serialnumber

Join the Network World communities on Facebook and LinkedIn to comment on the topics that matter to you.

Copyright © 2021 IDG Communications, Inc.


About Author

Comments are closed.