Pete Hinchley: Retrieve Name of Hyper-V Host from Guest in WinPE

In this post I will explain how you can retrieve information about a Hyper-V host from a guest virtual machine after booting from a WinPE 10 boot WIM.

The steps in this post draw from the guidance provided on Keith's Consulting Blog, which in turn was inspired by an article from Johan Arwidmark.

I will start by assuming you have an existing WinPE 10 boot WIM. This can be generated manually using the Deployment Tools installed via the ADK, or it could be generated via MDT or SCCM.

For the sake of simplicity, I will assume the following steps are performed on a server with the ADK installed, and with the boot WIM conveniently located at C:\Temp\winpe.wim. I'll also assume you have access to a Windows Server 2012 R2 server with the Hyper-V role enabled.

mkdir C:\Mount
dism /mount-wim /wimfile:C:\Temp\winpe.wim /index:1 /mountdir:C:\Mount
copy "C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe" C:\Mount\Windows\devcon.exe
Function CreateFakeService(sName, sDisplayName, sPathName)
  Dim objService
  Dim objInParam

  ' Obtain the definition of the Win32_Service class.
  Set objService = GetObject("winmgmts:root\cimv2").Get("Win32_Service")

  ' Obtain an InParameters object specific to the Win32_Service.Create method.
  Set objInParam = objService.Methods_("Create").inParameters.SpawnInstance_()

  ' Add the input parameters.
  objInParam.Properties_.item("Name") = sName
  objInParam.Properties_.item("DisplayName") = sDisplayName
  objInParam.Properties_.item("PathName") = sPathName
  objInParam.Properties_.item("ServiceType") = 16
  objInParam.Properties_.item("ErrorControl") = 0
  objInParam.Properties_.item("StartMode") = "Manual"
  objInParam.Properties_.item("DesktopInteract") = False

  ' Execute the method and obtain the return status.
  CreateFakeService = objService.ExecMethod_("Create", objInParam).ReturnValue
End function

CreateFakeService "TermService", "Remote Desktop Service", "FakeService.exe"

Set oShell = CreateObject("Wscript.Shell")
oShell.Run "devcon install " & Chr(34) & "X:\Windows\System32\DriverStore\FileRepository\wvmic.inf_amd64_dc7abc857325efe9\wvmic.inf" & Chr(34) & " " & Chr(34) & "vmbus\{242ff919-07db-4180-9c2e-b86cb68c8c55}" & Chr(34), 0, 1
oShell.Run "cmd /c net start vmickvpexchange", 0, 1
mkdir C:\Temp\Extracted
expand C:\Temp\Windows6.x-HyperVIntegrationServices-x64.cab -f:* C:\Temp\Extracted
"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\DISM\dism.exe" /image:C:\Mount /add-driver /driver:C:\Temp\Extracted\amd64_wvmic.inf_31bf3856ad364e35_6.3.9600.16385_none_f2a11f2920629934\wvmic.inf
dism /unmount-wim /mountdir:C:\Mount /commit

At the point the boot WIM has been successfully configured, however, to ensure the Hyper-V Data Exchange Services are invoked, you must run C:\Windows\vmvic.vbs after booting the WIM.

In my case, the WIM was used as part of an SCCM task sequence, so I added a step at the beginning of the sequence (after restating in WinPE) to invoke the script:

cscript.exe X:\Windows\wvmic.vbs

To ensure the script was only initiated when the task sequence was run on a Hyper-V guest, I applied two filters (the first evaluates the value of a built-in task sequence variable, and the second is a WMI query against the root\cimv2 namespace:

_SMSTSInWinPE=TRUE
SELECT model FROM win32_computersystem WHERE model = 'Virtual Machine'

Finally, we can return to our original goal: retrieving information about the Hyper-V host from the guest within WinPE. After running wvmic.vbs to install the Hyper-V Data Exchange Services, we can return the name of the Hyper-V host by reading the following registry value:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\PhysicalHostName

For example, the following VBScript could be called from a task sequence to assign the name of the Hyper-V host to a variable named sHostName:

Set oShell = CreateObject("WScript.Shell")
sHostName = UCase(oShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\PhysicalHostName"))