Microsoft makes it possible to import virtual machines into Hyper-V using either the Hyper-V Manager or PowerShell’s Import-VM cmdlet. This functionality has existed for a long time, and in my experience, the virtual machine import process usually goes fairly smoothly. Sometimes, however, the import process can fail and you may not get a lot of information as to why the failure has occurred. Fortunately, Microsoft provides a tool that can help you to troubleshoot the problem.
The tool of choice for troubleshooting virtual machine import problems is a PowerShell cmdlet called Compare-VM. The Compare-VM cmdlet is fairly simple. Its job is to assess whether or not a particular Hyper-V host is capable of hosting the virtual machine that you wish to import. That functionality makes the Compare-VM cmdlet ideal for troubleshooting virtual machine import issues.
Compare-VM to the rescue
The Compare-VM cmdlet is one of those cmdlets that supports a large number of optional parameters, and the command syntax can get pretty complicated. Even so, using the cmdlet for basic virtual machine and host evaluation purposes is a simple process.
The way that you would use the cmdlet in a failed import situation really just depends on whether the virtual machine currently resides on a Hyper-V host or not.
If you have previously exported the virtual machine and now need to import the VM into Hyper-V, then you will need to locate the XML file that describes the virtual machine (Windows Server 2016 Hyper-V did away with the XML file). If you look at the image below, for example, you can see that in my case the XML file is named 047e8a12-50e2-446c-b42f-b834655449da.xml, and the file exists at f:\VMs\Mirage\Virtual Machines. The path and filename will be different for your VM. In the figure, I have opened the XML file so that you can see the type of configuration information that it contains.
If I wanted to run the Compare-VM cmdlet against this particular VM, then the command would look something like this:
Compare-VM -Path 'F:\vms\Mirage\Virtual Machines\047e8a12-50e2-446c-b42f-b834655449da.xml'
If on the other hand, the virtual machine Mirage already resided on a Hyper-V host, and I wanted to import it into a different Hyper-V host, then I would only have to provide the Compare-VM cmdlet with the virtual machine name and the name of the host that I want to import the virtual machine into. For example, if I wanted to import a virtual machine named Mirage into a Hyper-V host named Hyper-V-4, then I would use this command:
Compare-VM -Name Mirage -DestinationHost Hyper-V-4
It is worth noting that this command assumes that you are executing the command from the Hyper-V host that contains the virtual machine. It also assumes that the server is able to resolve the DNS hostname of the destination host and that you have permission to access the destination host.
Since we are talking about the Compare-VM cmdlet from the standpoint of trying to resolve a virtual machine import failure, you would probably expect the Compare-VM cmdlet to generate some sort of error, and indeed it does. If you look at the figure below, you can see what happened when I ran the Compare-VM cmdlet on one of my Hyper-V hosts. You can also see that the Incompatibilities section contains a number of numeric error codes.
So now we have a series of codes that reflect the reason why the virtual machine import process failed, but of course, the codes are meaningless by themselves. So the next challenge is to figure out what each of the codes means.
If you are like me, then your first instinct may be to try to look up the error codes on the Internet. In fact, I tried doing just that as I was preparing to write this article because I had hoped to find some sort of master list of Compare-VM incompatibility codes. Unfortunately, Microsoft does not seem to provide such a list. If you do happen to know of such a list though, please post a link in the comments section below this article.
In the meantime, since there does not seem to be a master list of codes available, we have to get a description of the error codes in a different way. Once again, PowerShell can help us out. The trick is to map the Compare-VM cmdlet to a variable. Once we have done that, we can use the variable to extract information about the error codes.
For the purposes of this article, I am going to create a variable named $Compare. You can use any variable name that you like, but that is the name that I will be using. Here is the command that I will be using to populate the $Compare variable:
$Compare = Compare-VM -Name Mirage -DestinationHost Hyper-V-4
After executing the command, you can verify that the variable was correctly populated by entering the variable name into PowerShell. If you look at the figure below, for example, you can see that typing $Compare now provides the same output as running the Compare-VM cmdlet directly.
Now, if I want to see more information about the error codes, I can just type the variable name, followed by a period and the word Incompatibilities. You can see an example in the figure below.
The problem with this output, of course, is that the error message is truncated. To see the full message, simply append the pipe symbol and Select-Object Message | FL. Now we have a series of error messages that we can actually read, as shown below.
Hyper-V import failure: Get to the root cause
As you can see, there are a number of things that can cause a virtual machine import to fail. By using the Compare-VM cmdlet, however, it is possible to determine the root causes of the failure.