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
)ので、これを調べることでフィルタすることができます。