TONYSO

Tonyso Credo: "Look for a pattern, and solve it for everything"

Hyper-V How To: Detect if you are inside a VM

Hyper-V How To: Detect if you are inside a VM

  • Comments 1
  • Likes

Sometimes, when troubleshooting or for forensic reasons, you may have to determine if an application is running inside a virtual machine. John Kelbley, co-author of Windows Server 2008 Hyper-V : Insiders Guide to Microsoft's Hypervisor, shares how.

One (relatively) simple way to detect key virtualization information is via WMI / WBEM.  You can use the root\CIM2 namespace and access  the Baseboard class (full of interesting BIOS information) to get a description of the "physical" system.  This class often includes information about the motherboard and chassis  - manufacture, model, serial number, other.   You can run the following VBS to get this info.

On Error Resume Next

Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20

arrComputers = Array(".")
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo "=========================================="
   WScript.Echo "Computer: " & strComputer
   WScript.Echo "=========================================="

   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_BaseBoard", "WQL", _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)

   For Each objItem In colItems
      WScript.Echo "Caption: " & objItem.Caption
      strConfigOptions = Join(objItem.ConfigOptions, ",")
         WScript.Echo "ConfigOptions: " & strConfigOptions
      WScript.Echo "   CreationClassName: " & objItem.CreationClassName
      WScript.Echo "         Description: " & objItem.Description
      WScript.Echo "        HostingBoard: " & objItem.HostingBoard
      WScript.Echo "         InstallDate: " & WMIDateStringToDate(objItem.InstallDate)
      WScript.Echo "        Manufacturer: " & objItem.Manufacturer
      WScript.Echo "               Model: " & objItem.Model
      WScript.Echo "                Name: " & objItem.Name
      WScript.Echo "OtherIdentifyingInfo: " & objItem.OtherIdentifyingInfo
      WScript.Echo "          PartNumber: " & objItem.PartNumber
      WScript.Echo "             Product: " & objItem.Product
      WScript.Echo "        SerialNumber: " & objItem.SerialNumber
      WScript.Echo "                 SKU: " & objItem.SKU
      WScript.Echo "              Status: " & objItem.Status
      WScript.Echo "                 Tag: " & objItem.Tag
      WScript.Echo "             Version: " & objItem.Version
      WScript.Echo
   Next
Next

Function WMIDateStringToDate(dtmDate)
WScript.Echo dtm:
    WMIDateStringToDate = CDate(Mid(dtmDate, 5, 2) & "/" & _
    Mid(dtmDate, 7, 2) & "/" & Left(dtmDate, 4) _
    & " " & Mid (dtmDate, 9, 2) & ":" & Mid(dtmDate, 11, 2) & ":" & Mid(dtmDate,13, 2))
End Function

Here is a screen capture of the script results for a physical system running Windows Server 2008. 

image

NOTE the motherboard was manufactured by Intel  (model DG45ID).

Running the same script in a virtual machine returns similar information:

image

NOTE On the virtual machine, the "motherboard" appears to be made by Microsoft (we don't make motherboards!) and is of a virtual type.

The version number shown reflects the version of Hyper-V (Server 2008 RTM), and the Serial Number matches that found in the VM configuration file (XML file on the physical host).

The Perl script version for this is:

use strict;
use Win32::OLE('in');

use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;

my @computers = (".");
foreach my $computer (@computers) {
   print "\n";
   print "==========================================\n";
   print "Computer: $computer\n";
   print "==========================================\n";

   my $objWMIService = Win32::OLE->GetObject("winmgmts:\\\\$computer\\root\\CIMV2") or die "WMI connection failed.\n";
   my $colItems = $objWMIService->ExecQuery("SELECT * FROM Win32_BaseBoard", "WQL",
                  wbemFlagReturnImmediately | wbemFlagForwardOnly);

   foreach my $objItem (in $colItems) {
      print "          Caption: $objItem->{Caption}\n";
      print "       ConfigOptions: " . join(",", (in $objItem->{ConfigOptions})) . "\n";
      print "   CreationClassName: $objItem->{CreationClassName}\n";
      print "         Description: $objItem->{Description}\n";
      print "        HostingBoard: $objItem->{HostingBoard}\n";
      print "         InstallDate: $objItem->{InstallDate}\n";
      print "        Manufacturer: $objItem->{Manufacturer}\n";
      print "               Model: $objItem->{Model}\n";
      print "                Name: $objItem->{Name}\n";
      print "OtherIdentifyingInfo: $objItem->{OtherIdentifyingInfo}\n";
      print "             Product: $objItem->{Product}\n";
      print "        SerialNumber: $objItem->{SerialNumber}\n";
      print "                 SKU: $objItem->{SKU}\n";
      print "              Status: $objItem->{Status}\n";
      print "                 Tag: $objItem->{Tag}\n";
      print "             Version: $objItem->{Version}\n";
      print "\n";
   }
}sub WMIDateStringToDate(strDate)
{
   return "blah";
}

For additional reference, within Windows I could also access  the same information in a single command line (in Windows XP or newer) by typing  the following:

     wmic baseboard get manufacturer, product, Serialnumber, version

image

For info on how to use Hper-V PS cmdlets see: http://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/index.mspx

See also James O’Neil’s New and improved PowerShell Library for Hyper-V. Now with more functions and... documentation!

For 35 sample Hyper-V PS1 scripts in a zipfile, go to: Hyper-V%20PowerShell%20Example%20Scripts.zip-download

And buy John(et al)’s book!

image

Update: John's blogging now and has an updated method to detect the hypervisor: http://blogs.technet.com/enterprise_admin/archive/2009/10/20/detecting-the-virtualization-layer-from-within-a-guest-child-instance.aspx

Comments
  • I wasn't super clear when I provided this information to Tony - this shows a VM running on a Microsoft virtualization layer like Hyper-V.  A Windows virtual machine on VMWare does not report the same information (it may show that it has a 440BX chipset motherboard due to emulation).

    You can detect a VMware physical host by interrogating the WMI Win32_BIOS and looking at the serialnumber.  My buddy Ben Herman (you know who you are you scripting master!) helped me with that since I didn't have a VMware host handy.

    I'll send Tony some more info on all this that he can post.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment