Retrieve Basic Operating System Information with PowerShell
PowerShell version 5.1 added a new cmdlet named Get-ComputerInfo which retrieves lots of information from the local computer. It can be wrapped inside of the PowerShell remoting Invoke-Command cmdlet to retrieve that same information from remote computers.
My biggest complaint with Get-ComputerInfo
is that it takes forever to return the information and
then when it does finally complete, it's missing values for most of its properties. Also, if you're
going to wrap it inside of Invoke-Command
, then all of your remote machines would need PowerShell
5.1 or higher installed.
Because of these shortcomings, I decided to write my own simple function to retrieve just the operating system information I wanted while relying on CIM sessions for remote connectivity so down level clients could also be queried.
1#Requires -Version 3.0
2function Get-MrOSInfo {
3
4<#
5.SYNOPSIS
6 Gets basic operating system properties.
7
8.DESCRIPTION
9 The Get-MrOSInfo function gets basic operating system properties for the local computer or for one or more remote
10 computers.
11
12 .PARAMETER CimSession
13 Specifies the CIM session to use for this function. Enter a variable that contains the CIM session or a command that
14 creates or gets the CIM session, such as the New-CimSession or Get-CimSession cmdlets. For more information, see
15 about_CimSessions.
16
17.EXAMPLE
18 Get-MrOSInfo
19
20.EXAMPLE
21 Get-MrOSInfo -CimSession (New-CimSession -ComputerName Server01, Server02)
22
23.INPUTS
24 None
25
26.OUTPUTS
27 PSCustomObject
28
29.NOTES
30 Author: Mike F Robbins
31 Website: http://mikefrobbins.com
32 Twitter: @mikefrobbins
33#>
34
35 [CmdletBinding()]
36 param (
37 [Microsoft.Management.Infrastructure.CimSession[]]$CimSession
38 )
39
40 $Params = @{}
41
42 if ($PSBoundParameters.CimSession) {
43 $Params.CimSession = $CimSession
44 }
45
46 $OSInfo = Get-CimInstance @Params -ClassName Win32_OperatingSystem -Property Caption, BuildNumber, OSArchitecture, CSName
47
48 $OSVersion = Invoke-CimMethod @Params -Namespace root\cimv2 -ClassName StdRegProv -MethodName GetSTRINGvalue -Arguments @{
49 hDefKey=[uint32]2147483650; sSubKeyName='SOFTWARE\Microsoft\Windows NT\CurrentVersion'; sValueName='ReleaseId'}
50
51 $PSVersion = Invoke-CimMethod @Params -Namespace root\cimv2 -ClassName StdRegProv -MethodName GetSTRINGvalue -Arguments @{
52 hDefKey=[uint32]2147483650; sSubKeyName='SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine'; sValueName='PowerShellVersion'}
53
54 foreach ($OS in $OSInfo) {
55 if (-not $PSBoundParameters.CimSession) {
56 $OSVersion.PSComputerName = $OS.CSName
57 $PSVersion.PSComputerName = $OS.CSName
58 }
59
60 $PS = $PSVersion | Where-Object PSComputerName -eq $OS.CSName
61
62 if (-not $PS.sValue) {
63 $Params2 = @{}
64
65 if ($PSBoundParameters.CimSession) {
66 $Params2.CimSession = $CimSession | Where-Object ComputerName -eq $OS.CSName
67 }
68
69 $PS = Invoke-CimMethod @Params2 -Namespace root\cimv2 -ClassName StdRegProv -MethodName GetSTRINGvalue -Arguments @{
70 hDefKey=[uint32]2147483650; sSubKeyName='SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine'; sValueName='PowerShellVersion'}
71 }
72
73 [pscustomobject]@{
74 ComputerName = $OS.CSName
75 OperatingSystem = $OS.Caption
76 Version = ($OSVersion | Where-Object PSComputerName -eq $OS.CSName).sValue
77 BuildNumber = $OS.BuildNumber
78 OSArchitecture = $OS.OSArchitecture
79 PowerShellVersion = $PS.sValue
80
81 }
82
83 }
84
85}
One of the most difficult parts of writing this function was figuring out how to query the registry of a remote computer with a CIM session. I also didn't want to retrieve the information from one remote computer at a time. Instead, I wanted to retrieve the information for all of the computers at once and then put the pieces together before returning the information. While this is a little more complicated than query one computer at a time, the added efficiency and reduced run-time makes it worth the effort.
Simply run the function with no parameters to retrieve information from the local computer.
1Get-MrOSInfo
Now, I'll create CIM sessions to several different servers running different operating system versions and various versions of PowerShell.
1$CimSession = New-MrCimSession -ComputerName dc01, sql05, sql08, sql14, srv1, srv2
2$CimSession
Notice that by using my New-MrCimSession
function, it automatically created all of the ones
capable of using the WSMan protocol using it and the one that wasn't using the DCom protocol. The
SQL05 server runs Windows Server 2008 (non-R2) and does not have PowerShell installed at all.
1Get-MrOSInfo -CimSession $CimSession
The version number such as 1511, 1607, 1703, or 1709 will only show up for machines running Windows
10 or Server 2016 (or higher if you're reading this in the future), but the neat thing is the
Get-MrOSInfo
function is able to query down level servers such as SQL05 that do not have
PowerShell installed.
I went ahead and added PowerShell version 1.0 to my SQL05 server. When the same command is run
again, it shows that server does indeed now have PowerShell 1.0 installed. That particular version
of PowerShell does not include remoting or the ability to return the version with the
$PSVersionTable
built-in variable.
1Get-MrOSInfo -CimSession $CimSession
Both the Get-MrOSInfo
and New-MrCimSession
functions shown in this blog article can be
downloaded from my PowerShell repository on GitHub.
µ