Thursday, July 13, 2017

Hyper-V and PowerShell - A Tale of Two Modules

I've been working on a book project (see: http://tfl09.blogspot.co.uk/2017/04/my-next-powershell-book.html for details!) and have been working a lot with Hyper-V. I've built a nice farm of VMs (18 or so) representing a bunch of server roles and features. Then, I've been using PowerShell to exercise those roles and features.

These VMs all run on client Hyper-V, on a Windows 10 (AU) host that has 96gb or ram, 2x6-core XEON processors, and loads of disk. The VMs are nearly all running Windows 2016 Server. The chapters all utilise AD/DNS/DHCP/CA etc. A nice setup for writing a book.

In writing, I've noticed that Windows 10 as well as Windows Server 2016 both ship with two Hyper-V modules. The two modules are version 1.1 and 2.0.0.0, as you can see here:


The version 2.0.0.0 module is a superset of the version 1.1 module. Version 1.1 contains 178 cmdlets, while  version 2.0.0.0 contains 235. Both modules have display XML included. Both versions use the same file name, but the Version 2.0.0.0 copy is larger.

You could, or course, manually load version 1.1 module like this:
Import-Module -Name Hyper-V -MaximumVersion 1.1
So long as you just use the cmdlets in the 1.1 version, you would be safe, but if your script did load 1.1, then trying to use cmdlets in the 2.0.0.0 module generates what at first sight is a curious message:


The error message is also both wrong and, if taken, confusing. Importing the module as suggested by the error message generates more error messages. The error messages (Error in TypeData, etc) occur because Powershell is trying to load the version 2.0.0.0 copy of the display XML, and most of the components were already loaded from the 1.1 version. And even if you ignore the display XML errors, the suggested solution still fails with the same error message.

The solution to this error is easy: update your scripts to not explicitly load v1.1. OR, if you do need for some reason to use the 1.1 version and use cmdlets in 2.0.0.0, then pressed them with a 'Get-Module Hyper-V | Remove-Module Hyper-V' and then follow the 2.0.0.0 cmdlet with commands to remove the module and reload the 1.1 version. Personally, while that could work, it's awfully messy and possibly not needed.

Does having two versions really matter?  If you just use cmdlet names in the Hyper-V module, such as Get-VM, then PowerShell by default loads version 2.0.0.0.  If your script uses Import-Module to load the Hyper-V module explicitly, then again by default, PowerShell loads 2.0.0.0.  Having written over 100 scripts across a dozen different Server 2016 features and roles - I never noticed any problems. My scripts, with a few exceptions, relied on PowerShell's module autoload feature - I called the cmdlet and PowerShell loaded one.

If your scripts, on the other hand, explicitly load V 1.1 (as shown above), then you may get a strange error. But in most cases, that can be avoided by simply not explicitly loading version 1.1 of the module. Now I know there may be cases where you may need to use a V 1.1 cmdlet, but those cases should be pretty rare.


No comments: