PowerShellでインフラ系のスクリプトを作っていると、システムの情報を参照したいときがあります。
 Windowsならsysteminfoコマンドで表示させることができますが、これをPowerShellで取得してみます。といってもWMIオブジェクトを呼んでいるだけなので、C#など他のWindowsネイティブな言語でも同様にできるはず。
もくじ:
PowerShellによるコンピュータ情報の取得
まずはサンプル全体を掲載しておきます。
 get_systeminfo関数はWMIオブジェクトのプロパティ値を整形し、JSON文字列を返します。本来はクラスの細かい操作などあるのですが、動けばよしということで。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | function get_systeminfo(){     $result = @{"sys"=@{}; "cpu"=@{}; "bios"=@{}; "os"=@{}; "nic"=@{}};     # general info     $obj = Get-WmiObject -Class Win32_ComputerSystem     $result.sys.model = $obj.Model;     $result.sys.name = $obj.Name;     $result.sys.core_num = $obj.NumberOfLogicalProcessors;     $result.sys.architecture = $obj.SystemType;     $result.sys.memory = "{0:N0} MB" -f ($obj.TotalPhysicalMemory / 1024 / 1024)     $result.sys.vender = $obj.Manufacturer;     # processor info     $obj = Get-WmiObject -Class Win32_Processor     $result.cpu.name = $obj.Name;     $result.cpu.description = $obj.Description;     $result.cpu.thread_num = $obj.NumberOfLogicalProcessors;     # bios info     $obj = Get-WmiObject -Class Win32_Bios     $date = [DateTime]::ParseExact($obj.ReleaseDate.Substring(0,8), "yyyyMMdd", $null);     $result.bios.description = "{0}, {1}, {2}, {3}" -f $obj.Manufacturer, $obj.Description, $obj.SMBiosBiosVersion, $date.ToString("yyyy/MM/dd")     $result.bios.serialnumber = $obj.SerialNumber;     # os info     $obj = Get-WmiObject -Class Win32_OperatingSystem     $result.os.os_name = $obj.Caption;     $result.os.os_version = "{0}, build {1}" -f $obj.Version, $obj.BuildNumber;     $date = [DateTime]::ParseExact($obj.InstallDate.Substring(0,14), "yyyyMMddHHmmss", $null);     $result.os.install_date = $date.ToString("yyyy/MM/dd, HH:mm:ss");     # nic info     $obj = Get-WmiObject -Class Win32_NetworkAdapter | where {$_.NetConnectionStatus -ne $null}     $conf = Get-WmiObject -Class Win32_NetworkAdapterConfiguration     $result.nic = @{"interface" = @()}     foreach ($item in $obj){         $buffer = @{}         $buffer.vendor = $item.Manufacturer;         $buffer.mac = $item.MACAddress;         $buffer.description = $item.Description;         $buffer.name = $item.NetConnectionID;         $buffer.addr_type = "static";         # fill configuration part         $conf_ = $conf | where {$_.Index -eq $item.Index}         foreach ($addr in $conf_.IPAddress){             if ($addr.IndexOf(":") -eq -1){                 $buffer.ipv4 = $addr;             }else{                 $buffer.ipv6 = $addr;             }         }         if ($conf_.DHCPEnabled){             $buffer.addr_type = "dynamic"             $buffer.dhcp_svr = $conf_.DHCPServer         }         $buffer.gateway = $conf_.DefaultIPGateway         $buffer.dns = $conf_.DNSServerSearchOrder         # append to interface list         $result.nic.interface += $buffer     }     $result.nic.nic_num = $obj.Count     return ConvertTo-Json $result -Depth 5 } | 
実行結果はこんな感じです。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | PS > . .\infra.ps1 PS > get_systeminfo {   "bios": {     "description": "..., ..., 0614, 2017/04/18",     "serialnumber": "System Serial Number"   },   "sys": {     "vender": "... Ltd.",     "architecture": "x64-based PC",     "memory": "4,192 MB",     "name": "...",     "core_num": 8,     "model": "..."   },   "os": {     "install_date": "...",     "os_version": "10.0.16299, build 16299",     "os_name": "Microsoft Windows 10"   },   "nic": {     "interface": [{         "ipv4": "192.168.100.122",         "description": "Realtek PCIe GBE Family Controller",         "dhcp_svr": "192.168.100.1",         "gateway": [           "192.168.100.1"         ],         "mac": "88:D7:F6-...",         "dns": [           "192.168.100.1"         ],         "name": "イーサネット",         "addr_type": "dynamic",         "vendor": "Realtek",         "ipv6": "fe80:..."       },       {         "ipv4": "172.21.35.1",         "description": "Hyper-V Virtual Ethernet Adapter",         "dhcp_svr": "255.255.255.255",         "gateway": null,         "mac": "36:15:99...",         "dns": null,         "name": "vEthernet (既定のスイッチ)",         "addr_type": "dynamic",         "vendor": "Microsoft",         "ipv6": "fe80:..."       }     ],     "nic_num": 2   },   "cpu": {     "thread_num": 8,     "description": "Intel64 Family 6 ...",     "name": "Intel(R) Core(TM) i7-..."   } } | 
解説
上に掲載したスクリプトのポイントを簡単に記載しておきます。出力するオジェクトはテキトーに定義しているだけなので、必要に応じて適切な部分のみを使うやり方もありですね。
システム
ここではWin32_ComputerSystemオブジェクトを呼んでいます。
 プロパティ名から何の情報か予想できますが、systeminfoコマンド出力値と対応しているものがいくつかありますね。
| 1 2 3 4 5 6 7 8 | # general info $obj = Get-WmiObject -Class Win32_ComputerSystem $result.sys.model = $obj.Model; $result.sys.name = $obj.Name; $result.sys.core_num = $obj.NumberOfLogicalProcessors; $result.sys.architecture = $obj.SystemType; $result.sys.memory = "{0:N0} MB" -f ($obj.TotalPhysicalMemory / 1024 / 1024) $result.sys.vender = $obj.Manufacturer; | 
ちょっとわかりにくいところを挙げると、プロパティの.Nameがいわゆるホスト名を表すところや、物理メモリ.TotalPhysicalMemoryがバイト数で返されるところですかね。
プロセッサ
CPUの情報を格納しているWin32_Processorオブジェクト。
 パソコンのときはともかく、複数ソケットがサポートされているようなサーバマシンでは配列が返ってくるようです。
| 1 2 3 4 5 | # processor info $obj = Get-WmiObject -Class Win32_Processor $result.cpu.name = $obj.Name; $result.cpu.description = $obj.Description; $result.cpu.thread_num = $obj.NumberOfLogicalProcessors; | 
他にも製造元(.Manufacturer, この場合はIntel)とか、チップセット形状(.SocketDesignation, LGA何ちゃら)も取れるようになっています。
BIOS
BIOSの情報を格納しているWin32_BIOSオブジェクト。
| 1 2 3 4 5 | # bios info $obj = Get-WmiObject -Class Win32_Bios $date = [DateTime]::ParseExact($obj.ReleaseDate.Substring(0,8), "yyyyMMdd", $null); $result.bios.description = "{0}, {1}, {2}, {3}" -f $obj.Manufacturer, $obj.Description, $obj.SMBiosBiosVersion, $date.ToString("yyyy/MM/dd") $result.bios.serialnumber = $obj.SerialNumber; | 
.ReleaseDateプロパティにはBIOSのリリース日(インストールされた日ではありません)が格納されていますので、DateTimeオブジェクトとしてパースすることもできます。ここでは年月日に区切りを入れているだけなので、ちょっとやりすぎなのですが。
 systeminfoコマンド出力値に「BIOSバージョン」の項目がありますが、どうやら単純なバージョン番号のみではないようですね。
OS
OS、というか稼働しているWindowsの情報を格納しているWin32_OperatingSystemオブジェクト。
| 1 2 3 4 5 6 | # os info $obj = Get-WmiObject -Class Win32_OperatingSystem $result.os.os_name = $obj.Caption; $result.os.os_version = "{0}, build {1}" -f $obj.Version, $obj.BuildNumber; $date = [DateTime]::ParseExact($obj.InstallDate.Substring(0,14), "yyyyMMddHHmmss", $null); $result.os.install_date = $date.ToString("yyyy/MM/dd, HH:mm:ss"); | 
特にわかりにくいところはないと思います。.InstallDateは字面ではOSがインストールされた日ですが、適用している場合は直近の大型アップデートがインストールされた日になります。
 また、.SerialNumberでプロダクトIDが取得できます。
ネットワーク(NIC)
ネットワーク情報は、アダプタ(デバイス)を表すWin32_NetworkAdapterと、アダプタに適用されている設定を表すWin32_NetworkAdapterConfigurationに分かれています。
| 1 2 3 | # nic info $obj = Get-WmiObject -Class Win32_NetworkAdapter | where {$_.NetConnectionStatus -ne $null} $conf = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | 
Win32_NetworkAdapterの.NetConnectionStatusを調べると利用可能かどうかが分かります。MACアドレスやIPアドレスを調べるときには不要な、WAN miniportなどいわゆる仮想アダプタはこの値を持っていない($null)ので、これを調べることでフィルタすることができます。