How To: Configure Hyper-V Testing Environment To Play With Endpoint Management

I sometimes get asked how I experiment and learn new things with Microsoft Endpoint Manager and trial specific features or functions for customers and partners. I long ago adopted using virtual machines for rapid testing and I thought in this blog post I would show how I configure my testing environment with Hyper-V Virtual Machines.

I confess, I needed to rebuild these this morning as I recently rebuilt my Windows 11 laptop and forgot to save my Hyper-V snapshots of my test devices and therefore I lost all my virtual machines – not great practice! As this post is quite long, I’m going to create a quick table of contents below to let you jump to the relevant section you want to view quickly:

Getting Started – My Host Machine

I’m using a Surface Laptop 4 with Surface Dock and 2x external displays to make it easy to see both my virtual machines, Microsoft Documentation and the Endpoint Manager Admin Consolse, and here are the specs from Windows Settings of my device:

Device name SurfaceLaptop4
Processor 11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz 3.00 GHz
Installed RAM 16.0 GB (15.8 GB usable)
Device ID 61346483-XXXX-XXXX-XXXX-0A8A102FA6DA
Product ID 00330-XXXXX-XXXXX-AA634
System type 64-bit operating system, x64-based processor
Pen and touch Pen and touch support with 10 touch points

Edition Windows 11 Enterprise
Version 21H2
Installed on ‎22/‎04/‎2022
OS build 22000.675
Serial number 0317XXXXX057
Experience Windows Feature Experience Pack 1000.22000.675.0

A lot of the guidance below is taken and adapted from this guide and I always encourage you to read the original documentation as a source of truth to support you alongside my blog.

Enabling Hyper-V & Downloading ISO files

You need to be running Windows Enterprise or Education to be able to support Hyper-V on your device and run virtual machines and almost certainly this is not enabled by default. To turn this on you need to run a PowerShell command (in administrator mode):

With Powershell open, you need to run this command:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

This will prompt a restart of your computer to enable the hypervisor in Windows:

You will also need to download the Windows ISO file that will be used to load the operating system onto your virtual machines. You can choose either Windows 10 or Windows 11:

What actually happens is that you download an installer that will help guide you through the process of creating the ISO on your host device. Note, you do not want to upgrade your host PC, you’re wanting to create installation media. So when you run the installer you’ve downloaded it should look like this:

Choose your language and architecture (usually defaults for me):

You may want to create a USB with this if you want to use these ISO on physical machines, but if you’re just interested in creating virtual machines then you select ISO file:

Then choose a location to save these to – I generally create a c:\ISO\ folder and put all the various OS ISO in there:

Creating Virtual Machines In Hyper-V With PowerShell

Now that you’ve got the hypervisor enabled on your host machine and the ISO ready for install, it’s time to create the virtual machines. You can do this via the GUI of the Hyper-V Manager application itself but honestly, it’s quicker to do this from the command line using PowerShell

First of all, you need to determine the name of the network adaptor your host device is using – often there can be multiple, including wired / wireless and a simple PowerShell will determine this:

(Get-NetAdapter | Where-Object {$_.Status -eq "Up" -and !$_.Virtual}).Name

In my instance, it was just called Wi-Fi:

The next tip is to create a local folder where your VM are going to reside – I typically just use c:\Hyper-V\ and then I run the commands to create the new VM directly in that folder making it easier to know where they exist. To start with, you need to create a new virtual network adaptor for the virtual machines to interface with your host machine network adaptor:

New-VMSwitch -Name HyperV-Wifi -AllowManagementOS $true -NetAdapterName (Get-NetAdapter | Where-Object {$_.Status -eq "Up" -and !$_.Virtual}).Name

It’s worth noting the name section “-Name HyperV-Wifi” – that name that you choose will need to be referenced when you create the actual VM. With a virtual network adaptor created, you then create the virtual machine with the following code:

New-VM -Name Win10-OOBE -MemoryStartupBytes 4GB -BootDevice VHD -NewVHDPath .\VMs\Win10-OOBE.vhdx -Path .\VMData -NewVHDSizeBytes 80GB -Generation 2 -Switch HyperV-Wifi

It’s worth noting the variables here:

  • New-VM – Name
    • I called mine “Win10-OOBE” but this is the name of the VM and you need to keep this consistent in the following commands
  • -MemoryStartupBytes
    • I set mine at 4GB – you can assign more, but keep in mind the requirements of your host machine and how much available RAM you have
  • -BootDevice
    • VHD – going to use a virtual hard disk that will be defined
  • -NewVHDPath
    • This is a common default – making a subfolder in the location where you’re executing the command from (i.e. c:\Hyper-V\ for me)
    • Note that I have labelled the vhdx file the same as my -Name convention i.e. Win10-OOBE
  • -NewVHDSizeBytes
    • Defines the size of the virtual hard disk – I’ve used the default 80GB but it won’t actually take this much at the start – it will grow to that size as a maximum.
  • -Switch
    • This defines the virtual network switch that we created earlier – the name must be an exact match

With the VM created, you need to add the relevant ISO to the VM to boot:

Add-VMDvdDrive -Path c:\iso\Windows10.iso -VMName Win10-OOBE

Again, note the naming convention “-VMName Win10-OOBE” that needs to match the name of the VM we created above, and the correct path to where we saved the ISO earlier – both need to be exact matches.

You can easily create as many VM as you need using this with simple variable changes – e.g. here is a creation of a Windows 11 VM with a different name, location and ISO, but using the same virtual network switch:

New-VM -Name Win11-AutoPilot -MemoryStartupBytes 4GB -BootDevice VHD -NewVHDPath .\VMs\Win11-AutoPilot.vhdx -Path .\VMData -NewVHDSizeBytes 80GB -Generation 2 -Switch HyperV-Wifi

Add-VMDvdDrive -Path c:\iso\Windows11.iso -VMName Win11-AutoPilot

With the VM created, it’s time to turn it on and run through the Out Of Box Experience (OOBE).

Starting Your VM & Installing Windows 10

From within the Hyper-V Manager application you should now see all your VM that you’ve created. By clicking one and then choosing “Connect” you can connect to and start the VM:

One of the key benefits of using virtual machines for testing is that you can take snapshots of a VM at a point in time and then roll back/forward to that snapshot to test something again. I generally take a few snapshots through the setup process so I can start a demo from any point in time that the customer needs to see:

The first snapshot I typically take is when the Windows Setup process starts

One tip when setting these up to choose your correct geographic location under “Time and Currency Format” during this stage of the setup – I choose New Zealand so that the desktop timezone is set once I reach that point.

As these are testing machines, I typically don’t have or use a product key so select that option accordingly:

Then it’s important to choose the correct edition of Windows depending on what you want to test or demo. If you are wanting to use Intune to manage a device you need to choose Windows Pro or Education so it can be joined to AzureAD, but if you’re wanting to demo a “BYOD” device and going to do an AzureAD Register only with Windows Home then you can do that. Typically, I would have a Windows Home and Windows Pro VM for both Windows 10 and Windows 11 to allow me to demo each flavour.

Choose a custom install to wipe everything:

And install into the unallocated drive space:

At which point you’re pretty much done – depending on the speed of your host machine and how much RAM you allocated the virtual machine will determine how long it will take to configure:

At the Windows final OOBE configuration process I take another snapshot as this is a common “starting point” to roll back to show a customer:

After selecting region / keyboard / language / network options I typically create a final snapshot when it’s time to create an account. In the screenshot below this is for a Windows 10 Home Edition creating a local user (you cannot AD/AAD join a Windows Home device remember).

One tip here: Microsoft will drive you down the pathway of using an online Microsoft Account (MSA) to sign into Windows Home Edition rather than creating a local account. This is usually best practice, but for a demo device you likely don’t want to link your personal MSA to it. Therefore, if you temporarily turn off your host device wifi network then the guest VM can’t access the internet, forcing it to create a local user on the device:

Once the user is created, you have the active desktop and that’s the final snapshot I take during the setup process:

Windows 11 Considerations

There are a couple of considerations to keep in mind for Windows 11 in terms of your VM settings, specifically the number of virtual cores allocated and the TPM security settings.

You need a minimum of 4 virtual processors:

You also need the TPM enabled under security settings

Aside from that, the process is very similar to Windows 10 and you can see the flow below, although I use Windows 11 Pro and therefore have the option to add a work or school account and complete the AzureAD Join through the OOBE experience:

Again, it’s good practice to create snapshots along the way. I typically always snapshot at the “Add work or school account” stage as this is a common “roll back” point if I’m re-enrolling a device into Intune:

To complete the AzureAD Join make sure you select “Setup for Work or School”- note, you must have an internet connection for this option to be available. No internet, you’re going down the personal use and local user route:

This is where you can sign in with your school email address – provided the user has suitable licensing (AzureAD Premium 1 or 2 and Intune) then you’re going to enjoy a seamless experience:

With a password entered correctly you’re going to enjoy a short wait whilst configuration happens:

And within a minute or two you’re going to have an active desktop – note that in the background you can already see the Chrome Browser has been installed by Intune via an MSI package and added to the desktop shortcuts. This is a logical place to take a final snapshot:

If you want to check that the AzureAD Join has completed successfully you can do this under Settings -> Accounts -> Access Work or School

By clicking the “Info” button under the username, you’ll see what the MDM is managing and the last time a sync was attempted/successful:

Configuring For Windows AutoPilot

If you’re not familiar with Windows AutoPilot, it’s essentially a device registration service that allows for the collection of a unique hardware hash/identifier for a device and having that added/registered to your M365 Tenant allowing for zero touch onboarding. In some markets, a reseller/distributor can add these hardware identifiers to your tenant at the time of sale, or an IT admin can do it manually. There are a few ways to collect this hardware hash, but the easiest way in my mind in a VM environment is to use a PowerShell command during the OOBE setup.

I definitely want to give a hat tip to Scott Duffey and his great book Learning MEM where I learnt this.

So, to get started create a new VM with a suitable name to differentiate it from your other VM e.g.

New-VM -Name Win11-AutoPilot -MemoryStartupBytes 4GB -BootDevice VHD -NewVHDPath .\VMs\Win11-AutoPilot.vhdx -Path .\VMData -NewVHDSizeBytes 80GB -Generation 2 -Switch HyperV-Wifi

Add-VMDvdDrive -Path c:\iso\Windows11.iso -VMName Win11-AutoPilot

Once you’ve completed the Windows Setup and hit the OOBE stage, then hit “Shift + F10” to launch the command line:

The following commands come from this GitHub repository and work at time of publishing – note, those with a # in front of them are inline “comments” you don’t need to use these, just run the commands sequentially under each comment:

# At the OOBE, open a command prompt session. Shift F10 

# Launch PowerShell

# Set PowerShell Execution Policy
Set-ExecutionPolicy bypass

# Install the AutoPilot Script
install-script get-windowsautopilotinfo

# Run the Get Windows AutoPilot Info Command
Get-WindowsAutoPilotInfo.ps1 -online

# Login with Azure AD credentials when prompted

Here is a view of me adding the WindowsAutoPilotInfo script – note you do need to approve the adding of NuGet to get this to work:

Once you run the actual script it will pop open the familiar O365 authentication window and this needs to be authenticated with a Global Admin:

At that point, the script will harvest the unique hardware hash of your virtual machine and automatically upload it to Endpoint Manager’s enrolled devices list– there is no need to do any manual uploading of CSV files etc – this is a fantastic time saver.

Additionally, because the OOBE has not completed, Windows has not finished the install, you can simply reboot the virtual machine to kickoff the AutoPilot deployment. Before you do that, however, you may want to check the hardware hash has registered in Endpoint manager, so the place to check in the Admin Console is here, and it should look like this:

You can see that the serial number in Endpoint Manager matches the serial number identified in the PowerShell script above.

To configure AutoPilot to work in a zero touch ecosystem there are a few steps, basically:

  • Import the device hardware has (already done above)
  • Create and assign an AutoPilot Profile – guide
  • Create a device group for the AutoPilot devices – guide

Note: one tip is you can create a dynamic group in AzureAD that will automatically detect AutoPilot devices and put them into a group. This streamlines things even further. The query to identify and add AutoPilot devices to a dynamic group is:

(device.devicePhysicalIDs -any (_ -contains "[ZTDId]"))

(Hat tip to Stefan van der Busse for sharing that with me!)

  • Configure the Deployment Profile (this is what streamlines the set up for the end user by removing a lot of options/choices) – configure in Admin Console here:

Because I was running the dynamic group query to automatically add AutoPilot devices to this group, you can see the new device I registered above show up in this under “Assigned Devices” in the group:

Finally, to test the Windows AutoPilot zero touch deployment simply turn on (or reboot) the VM that you harvested the unique hardware hash from and depending on the settings you selected in the Deployment Profile you assigned above it should jump straight to the sign in screen:

Note in the above screenshot how it’s showing my school logo and also the customised message for IT help if required – this is the first screen the end user would see once the device has turned on and connected to the internet in the OOBE – they simply need to enter their email address and password to complete the AzureAD Join and Intune enrollment.

Final Thoughts

With this process, you can quickly create a virtual testing environment for various versions and editions of Windows and also leverage AutoPilot for testing purposes. It’s pretty straight forward to get up and running and in a future post I’ll show how to configure Intune to manage different settings and then use the Hyper-V snapshots to roll back and forward in testing.

Hope this helps – any questions or improvements on how you do things let me know in the comments below!

I am always keen to discuss what I've written and hear your ideas so leave a reply here...