Hyper-V generation 2 virtual machines – part 10

Part 1: Introduction to generation 2 virtual machines
Part 2: Networking and boot order
Part 3: Storage
Part 4: Keyboard for Windows 8 & Windows Server 2012
Part 5: Kernel debugging
Part 6: Secure Boot
Part 7: FAQ
Part 8: Manually migrating generation 1 virtual machines to generation 2
Part 9: Installing from ISO
Part 10: Utility for converting generation 1 virtual machines to generation 2 (Convert-VMGeneration)

The final part (at least for now, I’m hoping a guest author will write part 11) of this series on generation 2 virtual machines in Hyper-V re-visits conversion of a generation 1 virtual machine to a generation 2 virtual machine. Part 8 walked through the manual process, assuming it is possible. However, there is an easier way with a PowerShell script I wrote and recently released. Called Convert-VMGeneration.ps1, it can be downloaded from https://code.msdn.microsoft.com/ConvertVMGeneration. The script is intended to make life as simple as possible, reducing as many as reasonably possible manual post-migration fix-ups that may be required.

Convert-VMGeneration.ps1 is self-documenting – after downloading to a local drive, running get-help .\Convert-VMGeneration.ps1 –full will give you everything you need to know on how to use. I will assume that you have read part 8 of this series before use so you understand the three phases of conversion – capture, apply and clone.

A few tips worth mentioning:

  • Run reagentc /disable in the guest operating system prior to shutting down and converting (if reagentc /info indicates it is enabled). After conversion, in the generation 2 virtual machine, run reagentc /enable. This makes life a lot easier in terms of the Windows Recovery Environment and (lack of) manual intervention.
  • I strongly recommend you use the –Path parameter. Alternately, after a VM has been created, move the VM and its related storage to the right path using Hyper-V Manager. Note that if you subsequently perform a storage move, data-disks which were in use by the generation 1 virtual machine will no longer be valid from its perspective.
  • For the first few times of use, you might want to specify the name of the temporary .WIM file using the –WIM parameter, combined with –KeepWIM. That’ll save some time if a failure occurs during the apply or clone phases as you’ll not need to redo the potentially time-consuming capture phase. Using the -WIM parameter also makes it easier if you are running short of disk space and want to use an alternate location.
  • Be aware that you may not be able to start both the generation 1 and generation 2 virtual machines simultaneously (for example if they share a data VHDX). In reality, you really don’t want both machines on the network at the same time anyway. Be cautious of other implications too such as domain joined machine account passwords changing and so on.
  • Perform a move of the VM and all its data to another path after migration and you’ve verified the functionality of the converted generation 2 virtual machine. This will make it much cleaner to delete the old generation 1 virtual machine and clean up any old files which may be lingering.
  • The conversion performs a highly destructive step which completely wipes a disk. If everything is to plan, it’s the blank VHDX used as the boot disk for the generation 2 virtual machine. However, things could go wrong. For that reason, I strongly recommend you heed the warning (which cannot be suppressed) and make appropriate verifications. Should data loss occur for reasons such as coding error, no liability is assumed. If in doubt, export the generation 1 virtual machine, and import it onto a scratch box. Then do the conversion. That way, you are assured you will not lose anything important IF there is a bug.
  • Similar to HVRemote which some of you may have used, this script is not supported or endorsed by Microsoft Corporation.
  • Don’t close the PowerShell window while a conversion is in progress. Due to a bug in Windows, you may leave your system in a state whereby a drive letter is ‘leaked’ – it will be visible in Windows File Explorer, but unusable until the system is restarted. To cancel the script while it is progress, use Control-C and wait for it to clean-up instead.

Here’s an example of the conversion of a Windows Server 2012 virtual machine. The original virtual machine is highly available. The resulting generation 2 virtual machine will need to be made highly available after migration has completed.


Here’s an example where there are some (potential) issues to resolve. One is that there is an additional data partition on the boot disk for the source VM. Windows Recovery Environment was left enabled during the migration and will not operate correctly in the generation 2 virtual machine. Lastly, the original source boot disk was a differencing disk. Appropriate fix-ups may be required to mirror the configuration on the generation 2 virtual machine.


There are some VM configurations which aren’t handled, and the script will block the conversion:

  • The VM is running. The reason is simply that you cannot reasonably expect an operating system to continue running correctly if the firmware is fundamentally changed from under it.
  • Checkpoints (snapshots) are in use by the generation 1 virtual machine. The reasons partly relate to the above statement – an online checkpoint is equivalent to a running VM. While offline checkpoints could be converted in theory, there are further problems:
    • The mount-diskimage cmdlet that the script uses under the covers does not support .AVHDX files which are used by checkpoints. Further, the time to do the conversion would be prohibitive – each checkpoint would have to done individually.
    • Rebuilding the checkpoint tree with parent/child would be pretty much impossible – at best an individual offline checkpoint could be converted to a ‘standalone’ generation 2 virtual machine.
  • Hyper-V replica is enabled. The reason was simply my time to validate this scenario. In theory it should work. Obviously replica would need to be re-enabled after the conversion. The workaround is to disable replica prior to conversion, or use the “-IgnoreReplicaCheck” parameter.
  • When a guest cluster is configured in the generation 1 virtual machine using a shared VHDX. A highly available/clustered VM from the parent partition perspective works fine though. I am somewhat doubtful a guest cluster would come across cleanly, and have done no validation. The script hard blocks if any VHDX in the generation 1 virtual machine is shared.

I hope you find Convert-VMGeneration.ps1 useful. I’ll try to fix any bugs you report as time permits! A note for PowerShell aficionados reading the code – I make no apologies for my lack of PowerShell skills. This was the first time I’ve undertaken writing anything of reasonable complexity in PS. I’m sure there are many ways to make the code more powershellesque in efficiency.

So with that, I’ve reached the end of the planned parts of this series on generation 2 virtual machines in Hyper-V in Windows 8.1 and Windows Server 2012 R2. I hope you enjoyed them and found them and the conversion utility useful. As always, comments, questions and feedback are welcome.