Rapidly build Autopilot VMs with Hyper-V and PowerShell!

Picture this scenario – you are at the pointy end of a major modern management project and it’s time to test every policy, configuration and application at scale and quickly.

What do you do? With infinite money, infinite time and a willing client, you take over their VC meeting room and stack dozens of devices on a desk and blast slayer while you verify your builds ( this literally has happened to me)..

But what if you don’t have infinite money, time or an understanding client? That’s where Hyper-V and my latest module Intune.HV.Tools come in handy!

Over the last few days, me and my fellow nerd army (Steve, Adam and Bruce) have polished our VM provisioning script to something that we are proud enough to publish to the PowerShell Gallery.

Enough intro – let’s dive right in.

Open your favourite terminal as admin – PowerShell 5.1 or 7 will work. Haven’t installed 7 yet? give it a go, it’s easy to install and awesome.

Let’s begin by installing the module..

Once the module is installed, we need to set up our device using the functions contained within..

Let’s start by initializing everything..

All we are doing here is specifying where we want our VMs to be stored and preparing the configuration file – which we can look at by running the “Get-HVToolsConfig” command..

Now that we have our configuration file initialized, let’s add stuff to it!

The first thing we need to add is details of our windows installation media – in the example below we are using the latest “2004” build of windows 10..

We can add as many images to the solution as we want – all we need to do is make sure each one has a unique name – as shown below, I’ve added builds 1909 and 2004 to my lab..

Once we have our image library added to the config, let’s add some of our tenants (one at a time of course..)

What’s cool about the Add-TenantToConfig cmdlet is that the ImageName parameter autocompletes from the available images that we added in the step before. Only have one image? press Tab and it’ll autocomplete. You added a few images? Tab through and find the one you want to use!

Alright, we’ve got our images and our tenants configured, lastly we need to add our Hyper-V VLAN details – most of us probably just have the “Default Switch” that was set up when we install Hyper-V, but *some* of us have complex setups, so let’s solve that.

The cmdlet actually auto-completes against any virtual switches you might have set up, so as always, just tab through and find the switch you want to assign to your machines..

If you have a virtual network that requires a VLanID you can also apply that by using the -VlandID parameter..

Alright, once our configuration is set up, it’s time to build our VMs. For this example I’m going to build 3 VMs with a single CPU and 2gb of memory to enroll to the “Powers-Hell” tenant..

The first time you build a VM from an image it needs to create a reference image which can take some time – this will only need to be done once per image.

We will also check for any available Autopilot configuration profiles. If we want to skip that and just spin up test machines we can use the -SkipAutoPilot switch..

Once we’ve captured the Autopilot configuration profile we will use the local copy moving forward..

Let’s watch what happens once we already have the reference image created..

Awesome – we now have 3 machines we can use to verify our Autopilot configuration, all other Intune policies, configurations and applications work.

The usual caveat emptor rules apply – this works for me – I’ve tested it pretty heavily, but it may not work for you.

If it doesn’t work for you, please raise an issue on the GitHub and I’ll try fix it for you.

There are plenty of things I plan to add to this – so please check back regularly!

As always, Source code for this post can be found here, the official module can be found here, and I can always be reached on twitter.

— Ben


  1. Steve Whitcher
    May 26, 2020 at 7:16 pm

    I’m following your process here, but the ‘new-clientvm’ command seems to be missing. When I run ‘get-command -module intune.hv.tools’, the only functions I see are:

    This is running in Powershell 7.01 on Server 2016. Any suggestions?

    • Steve Whitcher
      May 26, 2020 at 7:39 pm

      Removing the module and importing it again seems to have corrected the above issue. I’m running into other issues now, but working my way through them. Thanks!

    • Ben
      June 2, 2020 at 5:40 am

      Very odd – the cmdlet is very much still in the module – i’d suggest deleting the content and re-downloading it.

    • Ben
      July 1, 2020 at 4:07 am

      Steve, I’ve actually found why you had this error and fixed it in the latest release.

  2. khalid
    June 21, 2020 at 5:00 pm

    Hi Ben,
    Running continuously into the same error code. “Cannot bind argument to parameter ‘vhdxPath’ because it is an empty string.” Any suggestion what could be wrong? Followed all your steps. thanks!

    • Ben
      June 22, 2020 at 2:41 am

      Can only suggest that you may have made a typo in the path to your installation media – if you feel like sharing the contents of your hvconfig.json file – type “Get-HVToolsConfig” I may be able to see where the issue is..

      • khalid
        June 29, 2020 at 6:01 pm

        Hi Ben,

        Thank you for your reply. T

        PS C:\Users\Administrator> get-command -module intune.hv.tools

        CommandType Name Version Source
        ———– —- ——- ——
        Function Add-ImageToConfig Intune.HV.Tools
        Function Add-NetworkToConfig Intune.HV.Tools
        Function Add-TenantToConfig Intune.HV.Tools
        Function Get-HVToolsConfig Intune.HV.Tools
        Function Initialize-HVTools Intune.HV.Tools
        Function New-ClientVM Intune.HV.Tools

        PS C:\Users\Administrator> Get-HVToolsConfig

        vSwitchName : External_IF0
        tenantConfig : {@{TenantName=NEXTPOINT; ImageName=2004; AdminUpn=**@**.be}}
        vLanId :
        hvConfigPath : E:\LAB\.hvtools\hvconfig.json
        images : {@{imageName=2004; imagePath=D:\ISO\en_windows_10_business_editions_version_2004_x64_dvd_d06ef8c5.iso; refImagePath=E:\LAB\.hvtools\tenantVMs\wks2004ref.vhdx}}
        vmPath : E:\LAB\.hvtools\tenantVMs

        • Ben
          July 1, 2020 at 4:11 am

          So without seeing how or where you are getting that error, is it possible that that reference vhdx isn’t there yet?

          May I also suggest to make sure you have the latest version of the module and try again.


  3. Christian
    September 4, 2020 at 4:23 am

    Hi Ben,
    Running continuously into the same error code. Any suggestions?

    PS C:\Windows\System32> New-ClientVM -TenantName ‘Train-Ing’ -NumberOfVMs 1 -CPUsPerVM 2 -VMMemory 4gb
    Grabbing Autopilot config..
    Policy found – saving to D:\VMs\.hvtools\tenantVMs\Train-Ing..
    Autopilot profile selected: TrainIng_Default
    Creating VM: Train-Ing_1..
    WARNING: Cannot process argument transformation on parameter ‘RefVHDX’. Cannot convert value to type System.String.

  4. Phil Ready
    September 28, 2020 at 6:47 pm

    Hi Ben, when adding inage to config, I get this error: Building reference image..Write-Error: The property ‘UniqueId’ cannot be found o n this object. Verify that the property exists.

Comments are closed.