【PowerShell】「仮想マシン」か「物理マシン」かを見分ける 2 ~ (2012.2.15 15:36 追記)

※ 2012.2.15 VMWare Workstation 6.5 – 7.x に関して追記しました(最後尾)
※ 2012.2.15 VMWare ESXi 4.1 に関して追記しました(最後尾)

※ 2012.2.14 VMWare Workstation 8 に関して追記しました(最後尾)

前回の投稿は以下の通りです。

【PowerShell】「仮想マシン」か「物理マシン」かを見分ける 1

前回の投稿では、Windows PowerShell を使用して「仮想マシン」か「物理マシン」を見分ける方法についてご紹介しました。方法といっても、たった1行のスクリプトですが。

では、さらに一歩踏み込んで、どんなタイプの仮想マシンなのかを判断することはできないでしょうか?

そのヒントとなるスクリプトが Microsoft Deployment Toolkit  2012(MDT 2012) Beta で提供されていました。

ためしに、上記サイトから MDT 2012 Beta をダウンロードしてインストールしてみてください。以下のスクリプトが見つかるはずです。

C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Scripts\ZTIGather.wsf

※以前のMDTにも含まれていますので無理にダウンロードする必要はありません

以下にスクリプト内から GetVirtualizationInfo という Function を抜粋したものを掲載します。簡単にコメントも追記しておきました。ここに、さまざまな仮想化プラットフォームの識別方法が vbs で書かれています。重要なのはスクリプト内で赤く太字にした部分です。WMI の Win32_ComputerSystemWin32_BIOS を使用していることがわかります。つまり、Win32_ComputerSystem の Model プロパティで大まかに仮想化ベンダーを判定し、さらに Win32_BIOS の Version プロパティを使用してマイクロソフトの製品名を特定しています。

※ZTIGather.wsf 抜粋(スクリプト言語は VBS です)

'//--------------------------------------------------------------------------- '// Function: GetVirtualizationInfo() '// Purpose: Get virtualization details '//--------------------------------------------------------------------------- Function GetVirtualizationInfo

    Dim oInstance, oInstances Dim sVersionString Dim bIsVM, sVMPlatform Dim sVMHost, sVMName

    oLogging.CreateEntry "Getting virtualization info", LogTypeInfo

    ' Set variables based on the capabilities of the hardware

    oEnvironment.Item("IsHypervisorRunning") = oUtility.ConvertBooleanToString(oUtility.BDDUtility.IsHypervisorRunning) oEnvironment.Item("SupportsVT") = oUtility.ConvertBooleanToString(oUtility.BDDUtility.SupportsVT) oEnvironment.Item("SupportsNX") = oUtility.ConvertBooleanToString(oUtility.BDDUtility.SupportsNX) oEnvironment.Item("Supports64Bit") = oUtility.ConvertBooleanToString(oUtility.BDDUtility.Supports64Bit) If oUtility.BDDUtility.SupportsVT and oUtility.BDDUtility.SupportsNX and oUtility.BDDUtility.Supports64Bit then oEnvironment.Item("SupportsHyperVRole") = "True" Else oEnvironment.Item("SupportsHyperVRole") = "False" End if

    ' Determine what virtual machine environment this might be. Get the BIOS version information

    Set oEnvironment = objWMI.ExecQuery("Select * from Win32_ComputerSystem")

    Set oInstances = objWMI.ExecQuery("Select * from Win32_BIOS") For each oInstance in oInstances sVersionString = oInstance.Version Next

    ' Check the BIOS version information against known values

    bIsVM = false sVMPlatform = ""

   If oEnvironment.Item("Model") = "Virtual Machine" then

        ' Microsoft virtualization technology detected, assign defaults

        sVMPlatform = "Hyper-V" bIsVM = true

        ' Try to determine more specific values

        Select Case sVersionString Case "VRTUAL - 1000831" bIsVM = true sVMPlatform = "Hyper-V Beta or RC0" Case "VRTUAL - 5000805", "BIOS Date: 05/05/08 20:35:56 Ver: 08.00.02" bIsVM = true sVMPlatform = "Hyper-V" Case "A M I - 2000622" bIsVM = true sVMPlatform = "VS2005R2SP1 or VPC2007" Case "A M I - 9000520" bIsVM = true sVMPlatform = "VS2005R2" Case "A M I - 9000816", "A M I - 6000901" bIsVM = true sVMPlatform = "Windows Virtual PC" Case "A M I - 8000314" bIsVM = true sVMPlatform = "VS2005 or VPC2004" End Select

        ' Try to get the VM host from the integration components

        sVMHost = "" On Error Resume Next sVMHost = oShell.RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Virtual Machine\Guest\Parameters\PhysicalHostNameFullyQualified") If Err then oLogging.CreateEntry "The VM physical host name was not found.", LogTypeVerbose Else oEnvironment.Item("VMHost") = sVMHost End if On Error Goto 0

        ' Try to get the VM namefrom the integration components

        sVMName = "" On Error Resume Next sVMName = oShell.RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Virtual Machine\Guest\Parameters\VirtualMachineName") If Err then oLogging.CreateEntry "The VM name was not found.", LogTypeVerbose Else oEnvironment.Item("VMName") = sVMName End if On Error Goto 0

    ElseIf oEnvironment.Item("Model") = "VMware Virtual Platform" then

        ' VMware detected

        sVMPlatform = "VMware" bIsVM = true

    ElseIf oEnvironment.Item("Model") = "VirtualBox" then

        ' VirtualBox detected

        bIsVM = true sVMPlatform = "VirtualBox"

    ElseIf oEnvironment.Item("Make") = "Xen" then

        ' Xen server detected

        bIsVM = true sVMPlatform = "Xen"

    Else oLogging.CreateEntry "This computer does not appear to be a virtual machine (BIOS is '" & sVersionString & "').", LogTypeInfo End if

    ' Set the appropriate variables

    oEnvironment.Item("IsVM") = oUtility.ConvertBooleanToString(bIsVM) If sVMPlatform <> "" then oEnvironment.Item("VMPlatform") = sVMPlatform End if

    oLogging.CreateEntry "Finished getting virtualization info", LogTypeInfo

End function

上記のスクリプトをごく簡単に PowerShell に書き換えたものが以下の通りです。

MS 製品と XEN は概ね確認しましたが、VMWare と VirtualBOX は確認しておりません。

どなたか、間違いがあればご指摘いただけるとうれしいです。

$oEnvironment = Get-WmiObject Win32_ComputerSystem $oInstance = Get-WmiObject Win32_BIOS

if ($oEnvironment.Model -eq "Virtual Machine") {     $vmPlatform = "Microsoft"     switch($oInstance.Version) {     "VRTUAL - 3000919" {$vmPlatform =  $vmPlatform + " Windows Server 2008 R2 Hyper-V"}     "VRTUAL - 5000920" {$vmPlatform =  $vmPlatform + " Windows Server 2008 Hyper-V"}     "A M I  - 2000622" {$vmPlatform =  $vmPlatform + " VS2005R2SP1 or VPC2007"}     "A M I  - 9000520" {$vmPlatform =  $vmPlatform + " VS2005R2"}     "A M I  - 9000816" {$vmPlatform =  $vmPlatform + " Windows Virtual PC"}     "A M I  - 6000901" {$vmPlatform =  $vmPlatform + " Windows Virtual PC"}     "A M I  - 8000314" {$vmPlatform =  $vmPlatform + " VS2005 or VPC2004"}        default {$vmPlatform =  $vmPlatform + "?????"}     } } elseif ($oEnvironment.Model -eq "VMware Virtual Platform") {     $vmPlatform = "VMWare" } elseif ($oEnvironment.Model -eq "VirtualBox") {     $vmPlatform = "Oracle VM VirtualBox" } elseif ($oEnvironment.Model -eq "HVM domU") {     $vmPlatform = "Xen" } else {     $vmPlatform = "unknown platform" }

$vmPlatform  

Xen については AWS の環境を借りて確認しました(クラウドって超便利!)。

image

単にベンダー識別するだけならば、Manufacture を見ればよさげですね。

参考までに、以下もご覧ください。

[Windows 7] XP Mode か実機か Virtual PC か Hyper-V か見分ける方法とは? - 管理者は見た!~AD と ILM 一家の秘密~ - Site Home - TechNet Blogs

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

2012.2.14 23:36 追記

@YoshihiroOkabe さんが VMWare Workstation 8 で検証してくださいました。

その結果、Model = Virtual Machine (← MS製品と同じ)であることが判明。全製品同様というわけでは無いと思われますが、少なくとも Manufacture も判断材料に入れないと正確には識別できないことがわかりました。

image

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

2012.2.15 0:16 追記

@GUCHI2010 さんが VMWare ESXi4.1 で検証してくださいました。

こちらは、Model = "VMware Virtual Platform" になるとの情報をいただきました。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

2012.2.15 15:43 追記

えぬなんとかわーるど の 山市良さんからも情報をいただきました

※詳しくはコメント欄をご覧ください

(ご参考)山市良のえぬなんとかわーるど: 仮想マシンのホスト環境をゲストからどこまで識別できるのか?