Page 1 of 1

How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 03:51
by spinjector
I tried searching for this, but the keywords are too common and I received an avalanche of useless search results.

How can Windows tell it's running in a Vbox guest window..? I need to create some batch files that run differently depending if the disk image is on real hardware or a vm. In this particular case, I found my own easy way: it's for Windows PE and the %systemdrive% environment variable is always the x: drive. But what if it's a normal version of Windows running on the C: drive..? Then how could it be done..?

Thanks.

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 10:09
by socratis
Set your own environment variable? Write a file? Create a directory? All of the above?

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 14:26
by scottgus1
In a default installation in an unmodified Virtualbox guest, some of the pieces of hardware the Windows OS sees may have "Virtualbox" in the name.

Run "msinfo32" or look at the Device Manager. Also consider what you see if Guest Additions aren't installed.

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 16:23
by mpack
The OP wants something which is scriptable, which AFAIK none of those methods are. He'd have to write a small app to do some tests and return an result code to the script.

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 17:06
by scottgus1
Right, I think WMI will do it, which can run in a VBscript.

In a fresh install of Windows 7 in a guest, no Guest Additions, the "root\CIMV2" namespace, "Win32_DiskDrive" class finds a disk with a "caption" and "model" of "VBOX HARDDISK ATA Device" and a "PNPDeviceID" with "VBOX HARDDISK" in the text.

This VBscript returns these values along with a bunch of other stuff that could be removed (courtesy of Microsoft Sysinternals WMI Scriptomatic):

Code: Select all

On Error Resume Next

Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20

strComputer = "."
   WScript.Echo
   WScript.Echo "=========================================="
   WScript.Echo "Computer: " & strComputer
   WScript.Echo "=========================================="

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

   For Each objItem In colItems
      WScript.Echo "Availability: " & objItem.Availability
      WScript.Echo "BytesPerSector: " & objItem.BytesPerSector
      strCapabilities = Join(objItem.Capabilities, ",")
         WScript.Echo "Capabilities: " & strCapabilities
      strCapabilityDescriptions = Join(objItem.CapabilityDescriptions, ",")
         WScript.Echo "CapabilityDescriptions: " & strCapabilityDescriptions
      WScript.Echo "Caption: " & objItem.Caption
      WScript.Echo "CompressionMethod: " & objItem.CompressionMethod
      WScript.Echo "ConfigManagerErrorCode: " & objItem.ConfigManagerErrorCode
      WScript.Echo "ConfigManagerUserConfig: " & objItem.ConfigManagerUserConfig
      WScript.Echo "CreationClassName: " & objItem.CreationClassName
      WScript.Echo "DefaultBlockSize: " & objItem.DefaultBlockSize
      WScript.Echo "Description: " & objItem.Description
      WScript.Echo "DeviceID: " & objItem.DeviceID
      WScript.Echo "ErrorCleared: " & objItem.ErrorCleared
      WScript.Echo "ErrorDescription: " & objItem.ErrorDescription
      WScript.Echo "ErrorMethodology: " & objItem.ErrorMethodology
      WScript.Echo "FirmwareRevision: " & objItem.FirmwareRevision
      WScript.Echo "Index: " & objItem.Index
      WScript.Echo "InstallDate: " & WMIDateStringToDate(objItem.InstallDate)
      WScript.Echo "InterfaceType: " & objItem.InterfaceType
      WScript.Echo "LastErrorCode: " & objItem.LastErrorCode
      WScript.Echo "Manufacturer: " & objItem.Manufacturer
      WScript.Echo "MaxBlockSize: " & objItem.MaxBlockSize
      WScript.Echo "MaxMediaSize: " & objItem.MaxMediaSize
      WScript.Echo "MediaLoaded: " & objItem.MediaLoaded
      WScript.Echo "MediaType: " & objItem.MediaType
      WScript.Echo "MinBlockSize: " & objItem.MinBlockSize
      WScript.Echo "Model: " & objItem.Model
      WScript.Echo "Name: " & objItem.Name
      WScript.Echo "NeedsCleaning: " & objItem.NeedsCleaning
      WScript.Echo "NumberOfMediaSupported: " & objItem.NumberOfMediaSupported
      WScript.Echo "Partitions: " & objItem.Partitions
      WScript.Echo "PNPDeviceID: " & objItem.PNPDeviceID
      strPowerManagementCapabilities = Join(objItem.PowerManagementCapabilities, ",")
         WScript.Echo "PowerManagementCapabilities: " & strPowerManagementCapabilities
      WScript.Echo "PowerManagementSupported: " & objItem.PowerManagementSupported
      WScript.Echo "SCSIBus: " & objItem.SCSIBus
      WScript.Echo "SCSILogicalUnit: " & objItem.SCSILogicalUnit
      WScript.Echo "SCSIPort: " & objItem.SCSIPort
      WScript.Echo "SCSITargetId: " & objItem.SCSITargetId
      WScript.Echo "SectorsPerTrack: " & objItem.SectorsPerTrack
      WScript.Echo "SerialNumber: " & objItem.SerialNumber
      WScript.Echo "Signature: " & objItem.Signature
      WScript.Echo "Size: " & objItem.Size
      WScript.Echo "Status: " & objItem.Status
      WScript.Echo "StatusInfo: " & objItem.StatusInfo
      WScript.Echo "SystemCreationClassName: " & objItem.SystemCreationClassName
      WScript.Echo "SystemName: " & objItem.SystemName
      WScript.Echo "TotalCylinders: " & objItem.TotalCylinders
      WScript.Echo "TotalHeads: " & objItem.TotalHeads
      WScript.Echo "TotalSectors: " & objItem.TotalSectors
      WScript.Echo "TotalTracks: " & objItem.TotalTracks
      WScript.Echo "TracksPerCylinder: " & objItem.TracksPerCylinder
      WScript.Echo
   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
Note, to run the Scriptomatic correctly, make a shortcut to the downloaded hta file, then edit the "Target" to add "mshta.exe{space}" before the path to the hta file. Click OK to accept the new path, which should be "mshta.exe driveletter:\path\to\ScriptomaticV2.2.hta" Right-click the shortcut and choose Run As Administrator.

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 17:13
by socratis
Wait a minute, installing Windows unattended, potentially installing GAs and/or other goodies is scriptable, and creating "C:\Users\I_am_a_VM" on the guest is not? Or checking for its existence?

Re: How can Windows tell it's running on a VM..?

Posted: 29. Nov 2016, 17:21
by scottgus1
Looking for a special file would work, but if someone forgets to place the file, in the midst of all the other things one has to do to bring a new install into the mix, then the script would fail. My thought is that scripting a hunt for Virtualbox-specific hardware names or some other such would allow his special script to run successfully without needing to look for a manually-placed file, which someone may one day forget to make. As long as the developers don't change the hardware names the OP should be good.

Of course if there is a way to run a script on the host that automatically during or after the OS installation causes a special file to be made on the guest, then that would work too.