#PSTip Pause after UEFI boot failure when using Hyper-V Generation 2 virtual machines

Hyper-V in Windows 8.1 and Windows Server 2012 R2 introduced Generation 2 virtual machines, which provides new feature and better performance. One of the new features is UEFI, a replacement of the traditional BIOS. When troubleshooting boot problems on Generation 2 virtual machines, for example as part of a new image build, one of the issues is that the boot process is so fast it is hard to follow what is happening.

For advanced users, there is a CIM property in the Msvm_VirtualSystemSettingData class called PauseAfterBootFailure:

Get-CimClass -Namespace 'Root\Virtualization\V2' -ClassName Msvm_VirtualSystemSettingData |
Select-Object -ExpandProperty CimClassProperties | where name -eq "PauseAfterBootFailure"

Name               : PauseAfterBootFailure
Value              :
CimType            : Boolean
Flags              : Property, NullValue
Qualifiers         : {read, write}
ReferenceClassName :

This property is by default set to $false. During troubleshooting it might be useful to enable this setting. Normally we would expect to accomplish this is by leveraging the CIM cmdlets:

Get-CimInstance -Namespace Root\Virtualization\V2 -ClassName Msvm_VirtualSystemSettingData -Filter "ElementName = 'Demo-VM'" |
Set-CimInstance -Property @{PauseAfterBootFailure=$true} –PassThru

Alternatively, by using Get-WmiObject:

$vm = Get-WmiObject -Class Msvm_VirtualSystemSettingData -Namespace Root\Virtualization\V2 -Filter "ElementName = 'Demo-VM'"
$vm.PauseAfterBootFailure = $true
$vm.Put()

Although these commands does not produce any error messages, the property remains unchanged.

The reason for this is that the original WMI APIs did not provide a way to pass a WMI instance as the argument to a method directly; to pass an object to a method, you would serialize it into an embedded instance, a string representation of the object in XML form (using the ManagementObject.GetText method).

The Hyper-V WMI provider continues to expect any input objects in embedded-instance format, but the CimInstance objects retrieved by the CIM cmdlets do not currently provide a convenience method for serializing an object into an embedded instance.

#Virtual System Management Service
$VSMS = Get-CimInstance -Namespace root/virtualization/v2 -Class Msvm_VirtualSystemManagementService

#Virtual Machine
$VM = Get-CimInstance -Namespace root/virtualization/v2  -Class Msvm_ComputerSystem -Filter "ElementName='Demo-VM'"

#Setting Data
$SD = $vm | Get-CimAssociatedInstance -ResultClassName Msvm_VirtualSystemSettingData -Association Msvm_SettingsDefineState

#Update boot option
$SD.PauseAfterBootFailure = $True

#Create embedded instance
$cimSerializer = [Microsoft.Management.Infrastructure.Serialization.CimSerializer]::Create()
$serializedInstance = $cimSerializer.Serialize($SD, [Microsoft.Management.Infrastructure.Serialization.InstanceSerializationOptions]::None)
$embeddedInstanceString = [System.Text.Encoding]::Unicode.GetString($serializedInstance)

#Modify the system settings
Invoke-CimMethod -CimInstance $VSMS -MethodName ModifySystemSettings @{SystemSettings = $embeddedInstanceString}

When the PauseAfterBootFailure property is set to $true, the specified virtual machine will ask the user to press a key when a boot attempt failed:

Hyper-V PauseAfterBootFailure Illustration

The same technique can be used to modify other writable properties in the Msvm_VirtualSystemSettingData class.

Thanks to Brian Young at Microsoft for his assistance explaining this behavior.

About the author: Jan Egil Ring

Jan Egil works as a Lead Architect on the R&D Team at Crayon, Norway. He mainly works with automation, and has a strong passion for PowerShell. Products and services he works with includes Microsoft infrastructure products such as Windows Server, System Center and Microsoft Azure. He is a multiple-year recipient of Microsoft Most Valuable Professional Award for his contributions in the Windows PowerShell and Cloud & Datacenter Management technical communities. He speaks regularly at user groups and conferences, such as Nordic Infrastructure Conference (NIC), PowerShell Conference Europe and PowerShell Summit. He is a co-founder of the Norwegian Microsoft Technology User Group (MTUG), which is an association of local MTUG user groups in Norway. He is also co-organizing the MTUG Script Club which focuses mainly on PowerShell. You can follow him on Twitter @JanEgilRing.

Related Posts

%d bloggers like this: