Long time ago, being a young padawan in an organization I was tasked to do an inventory check on systems across our end-user machines. At first I have actually planned an old-school inventory, moving across the rooms and buildings, however decided against it. Instead I searched the internet for a flexible PowerShell script, that would allow me to perform the task remotely. That is how I have discovered a Windows Management Instrumentation with all the power it can give a network administrator.
Official documentation on Windows Management Instrumentation (WMI) can be found here.
For those out there who work with PowerShell scripts daily that might be old news, but for me it was a true salvation. Instead of walking around the office, I have spent roughly the same amount of time tailoring script to specific requirements of an inventory check from the comfort of my own cubicle. And have learned a lot of useful stuff along the way.
The “mighty” inventory script
I have recently stumbled upon this script again and decided to share it with you, to spare you the time of digging for specific commands and explanations.
You can find the actual script on my Bitbucket. So, let’s dive into it!
Before we begin:
- Obviously as WMI name implies, this will work if your infrastructure consist of Windows-based machines.
- Running PowerShell on remote hosts requires Administrative privileges in the network.
- The process is not lightning-fast. Depending on how many machines you want to scan, you might want to reserve some time for this process to finish. However, as it runs in the background, it doesn’t require your constant attention.
How to use this inventory script
Determine the scope in terms of IP address range that you want to check. If I am not targeting a specific workstation with a query, I usually prefer sweeping scan across the entire subnet, so no to miss any odd machines that might be connected to network.
Do not forget to review the name and path for your output file and run this script with elevated permissions.
What does this script do?
Now let’s dissect the PowerShell script itself to understand, how and what are we collecting. Depending on a query WMI cmdlets don’t always give a straightforward answer, however with some witty improvements of raw data, we are going to get what we are after.
I begin with a couple of helper functions. First Exists pings the potential endpoint address to see of anything is there at all. Script will poll only those addresses, that respond to it. Second, Decode helps to get human-readable form of system reply, when it is encoded in some way.
Next is the main loop. Here you should determine the range of scanned addresses. Heads up! If your network is larger than mine, you might need to iterate over third octet of the address as well.
We’ll make use of WMI technology, namely a Get-WmiObject cmdlet (short: gwmi). Accessing different classes script will collect data required for our inventory. For example
$os = gwmi Win32_OperatingSystem -Computer $ip
allows us to get following operating system properties of remote computer with IP address of $ip:
.Caption – a name of OS;
.BuildNumber – a number of current build (obviously);
.OSArchitecture – if your system is 32 or 64-bit
In similar way script will retrieve all the required info. However, some of the raw data will not be of much use to us. For example, RAM and disk sizes are returned in bits, so script will have to convert those to GB for us. Also video outputs and disk types are stored encoded as integer, so script will try and match returned values to eyes-friendly names to provide us meaningful results.
Once script has polled a machine for data, an object containing results is created and exported to CSV file. By default file named “inventory.csv” will be created in the same folder as script.
What information is collected?
My inventory script collects 13 properties as follows:
- IP – IPv4 address of the endpoint computer
- Name – computer name
- UserName – logged in user name (w/computer name)
- Serial – serial number of the machine
- Model – model of the machine
- OS – name of operating system
- Architecture – architecture of OS
- Build – build of OS
- RAM – RAM in GB (sums up all the available sticks)
- DiskSize – disk size in GB (NB! script assumes you are interested in disk C: only, might want to change that)
- DiskType – if this is SSD or HDD
- Monitors – contains names, serial numbers and years of manufacturing for all connected monitors
- VideoOuts – shows what slots are used to connect monitors to the computer*
*I have yet to discover how to match monitors with respective slots in output. For now in case you have more than one monitor, the order of information in Monitors and VideoOuts can be random.
Full script is available on Bitbucket. There are tons of ways to improve it or tailor to your own needs. Just a few ideas:
- Read the official documentation or search the web and add more queries to collect even more useful data with this script.
- Run this script as a scheduled task periodically to stay on top of any changes in your infrastructure. You might want to change the output file name to contain current date, to keep logs of all your runs.
- Going one step further, you can tweak this PowerShell script to take result of previous inventory as input and log changes only, comparing to previous configuration. (Will work better with DHCP reservations, than with leases). This will save you loads of work comparing the results manually.
Are there easier approaches? Sure! Is there an app for that? Of course there is, lots of those with varying level of sophistication. While my inventory PowerShell script will not give you a full picture of the hardware in your organization, as there might be various offline workstations either by design, or because the computer is simply not running. Some of machines might have WMI service not-running, or run another OS on board. Nevertheless, you will have much less legwork to do to cover the rest of infrastructure.
Have fun inventorying!
Cover image by Venveo