Skip to content

Easy Menu for Autopilot Group Tag

This post will give you ideas of my easy menu for autopilot group tag selection when registering devices for Autopilot. This was first briefly mentioned in my post covering Exclusive Computer Renaming with Intune and Azure, and the community has since requested more details.

The goal is to have the following menu for making the best decision on group tag when exporting the hardware hash for Autopilot.

Menu for Autopilot Group Tag

Please join me while I walk you through the technology behind this.

The Group Tags

Microsoft Autopilot is a tool that enables organizations to pre-configure and deploy new Windows devices quickly and efficiently. Autopilot group tags are used within Autopilot to assign a device to a specific group based on its intended use or purpose. Group tags can apply different configuration profiles, settings, or policies to devices depending on their assigned group, which can help streamline device deployment and management within an organization.

When deploying Windows devices using Microsoft Autopilot, one of the initial steps is to collect the hardware hashes of the devices. This can be done by running a PowerShell script on each device, which generates a unique hardware ID based on specific device hardware attributes. At this point, we can also include the group tag. These hardware hashes with the group tags are then uploaded to the Intune console, which is used to identify and enroll the devices into the Autopilot deployment program. The assigned group tag will then address the targeted configuration of the device.

The example in my first blog post used group tags to target the geographic naming convention for the computer name. An example list of group tags could be like this:

CountryCodeGroup Tag

This should then be used to construct computer names consisting of an ISO 2 character country code, a “-” separator followed by the serial number. Example: NO-132435465768

The group tag is a text string; an extra column in the hardware hash CSV file will represent it.

Dynamic Device Groups

Based on the Group Tag, the autopilot computer should become a member of an Azure AD Security group of type Dynamic Device. Autopilot devices that meet the rules for the group are automatically added to the group.

Intune’s group tag field maps to the OrderID attribute on Azure AD devices. To create a group that includes all Autopilot devices with a specific group tag (the Azure AD device OrderID), enter for instance: (device.devicePhysicalIds -any (_ -eq “[OrderID]:Device-NO”))

The membership rule for these groups will be as follows:

Dynamic Device AutoPilot GroupMembership Rule AutoPilot Group
AZ-SE-Autopilot-Computers(device.devicePhysicalIds -any _ -eq “[OrderID]:Device-SE”)
AZ-NO-Autopilot-Computers(device.devicePhysicalIds -any _ -eq “[OrderID]:Device-NO”)
AZ-DK-Autopilot-Computers(device.devicePhysicalIds -any _ -eq “[OrderID]:Device-DK”)
AZ-FI-Autopilot-Computers(device.devicePhysicalIds -any _ -eq “[OrderID]:Device-FI”)
AZ-DE-Autopilot-Computers(device.devicePhysicalIds -any _ -eq “[OrderID]:Device-DE”)

PowerShell script to create Device Groups

I have a PowerShell script for creating these device groups. It should, however have been rewritten to GraphAPI. This time the script is shared as it is. The script is based on a CSV file holding the country codes for each country. Here is an example of CountryCodes.csv


The script for creating the dynamic device group for Autopilot computers based on the CSV file looks like this:

    Purpose:    Create country based Dynamic Device Group in Azure AD for Autopilot computers.
    Author:    Simon Skotheimsvik

    remove-Module AzureAD -ErrorAction SilentlyContinue
    install-module AzureADPreview  -RequiredVersion -Force -AllowClobber

try {
    Get-AzureADTenantDetail -ErrorAction Stop > $null

catch {
    write-host "Authenticate with AzureAD"

$Countries = Import-Csv .\CountryCodes.csv -delimiter "," -encoding utf8

Foreach ($Country in $Countries) {
    # Variables from CSV
    $CountryName = $Country.Country.Trim()
    $CountryCode = $Country.Code.Trim()

    # Process for Dynamic Device group Autopilot Computers
    $GroupDisplayNameAutoPilot = "AZ-$CountryCode-Autopilot-Computers"
    $GroupDescriptionAutoPilot = "This group contains AutoPilot computers primarly located in $CountryName."
    $GroupMailNickNameAutoPilot = $GroupDisplayNameAutoPilot
    $GroupDynamicMembershipRuleAutoPilot = "(device.devicePhysicalIds -any _ -eq ""[OrderID]:Device-$CountryCode"")"

    write-host "Variables for $CountryName AutoPilot group has been calculated:" -ForegroundColor Yellow
    write-host `t "Name:" `t`t $GroupDisplayNameAutoPilot `n`t "Description:" `t $GroupDescriptionAutoPilot `n`t "Rule:" `t`t $GroupDynamicMembershipRuleAutoPilot

    if ($Group = Get-AzureADGroup -Filter "DisplayName eq '$GroupDisplayNameAutoPilot'") {
        write-host `t"Group exists. Parameters will be set" -ForegroundColor green
        Set-AzureADMSGroup -Id $Group.ObjectId -DisplayName $GroupDisplayNameAutoPilot -Description $GroupDescriptionAutoPilot -membershipRule $GroupDynamicMembershipRuleAutoPilot -membershipRuleProcessingState "On"
    else {
        write-host `t"Group does not exist. It will be created" -ForegroundColor red
        New-AzureADMSGroup -DisplayName $GroupDisplayNameAutoPilot -Description $GroupDescriptionAutoPilot -MailEnabled $False -MailNickName $GroupMailNickNameAutoPilot -SecurityEnabled $True -GroupTypes "DynamicMembership" -membershipRule $GroupDynamicMembershipRuleAutoPilot -membershipRuleProcessingState "On"

    # Process for Dynamic Device group All Computers
    $GroupDisplayNameDevice = "AZ-$CountryCode-All-Computers"
    $GroupDescriptionDevice = "This group contains all computers primarly located in $CountryName with computername starting with $CountryCode-."
    $GroupMailNickNameDevice = $GroupDisplayNameDevice
    $GroupDynamicMembershipRuleDevice = "(device.deviceOSType -contains ""Windows"") and (device.displayName -startsWith ""$CountryCode-"")"

    write-host "Variables for $CountryName All Computers group has been calculated:" -ForegroundColor Yellow

write-host `t "Name:" `t`t $GroupDisplayNameDevice `n`t "Description:" `t $GroupDescriptionDevice `n`t "Rule:" `t`t $GroupDynamicMembershipRuleDevice

    if ($Group = Get-AzureADGroup -Filter "DisplayName eq '$GroupDisplayNameDevice'") {
        write-host `t"Group exists. Parameters will be set" -ForegroundColor green
        Set-AzureADMSGroup -Id $Group.ObjectId -DisplayName $GroupDisplayNameDevice -Description $GroupDescriptionDevice -membershipRule $GroupDynamicMembershipRuleDevice -membershipRuleProcessingState "On"
    else {
        write-host `t"Group does not exist. It will be created" -ForegroundColor red
        New-AzureADMSGroup -DisplayName $GroupDisplayNameDevice -Description $GroupDescriptionDevice -MailEnabled $False -MailNickName $GroupMailNickNameDevice -SecurityEnabled $True -GroupTypes "DynamicMembership" -membershipRule $GroupDynamicMembershipRuleDevice -membershipRuleProcessingState "On"

Running this will create the groups.

The script will also create another set of groups based on the device name, not the group tag as the previous groups. These groups look like this:

These latter groups can convert existing AAD devices to Autopilot by targeting the groups in the deployment profiles.

Deployment Profiles

The idea is to have one deployment profile pr. group tag, and I have a script for deploying the profiles and assigning the dynamic autopilot device groups created earlier. This script is based on the same CSV file. This script should also be converted to GraphAPI.

    Purpose:    Create country based AutoPilot profiles.
    Author:    Simon Skotheimsvik

    Install-Module -Name WindowsAutoPilotIntune -Force -AllowClobber
Import-Module AzureAD
Import-Module WindowsAutoPilotIntune

try {
    Get-AutoPilotProfile -ErrorAction Stop > $null
catch {
    write-host "Authenticate with MSGraph"
try {
    Get-AzureADTenantDetail -ErrorAction Stop > $null
catch {
    write-host "Authenticate with AzureAD"

$Countries = Import-Csv .\CountryCodes.csv -delimiter "," -encoding utf8

Foreach ($Country in $Countries) {
    # Variables from CSV
    $CountryName = $Country.Country.Trim()
    $CountryCode = $Country.Code.Trim()

    # Process for AutoPilot Profiles
    $APDPDisplayName = "AZ $CountryCode Autopilot"
$GroupDisplayNameAutoPilot = "AZ-$CountryCode-Autopilot-Computers"
        # Hyphen notallowd in APDPDisplayName!
    $APDPDescription = "Autopilot Deployment profile for computers primarly located in $CountryName."
    $APDPDeviceNameTemplate = "$CountryCode-%SERIAL%"
    $APDPVariables = "-mode UserDrivenAAD -OOBE_Language ""os-default"" -OOBE_HideEULA -OOBE_HidePrivacySettings -OOBE_HideChangeAccountOpts -ConvertDeviceToAutopilot -OOBE_EnableWhiteGlove"

    write-host "Variables for $CountryName Autopilot Deployment Profile has been calculated:" -ForegroundColor Yellow
    write-host `t "Name:" `t`t $APDPDisplayName `n`t "Description:" `t $APDPDeviceNameTemplate `n`t "Rule:" `t`t $APDPDescription

    if ($APDP = Get-AutopilotProfile | Where-Object {$_.displayName -EQ $APDPDisplayName}) {
        write-host `t"Autopilot Deployment Profile exists. Parameters will be set" -ForegroundColor green
        # THIS GIVES AN 400 Bad Request ERRROR
#        Set-AutopilotProfile -id $ -displayName $APDPDisplayName #-Description $APDPDescription -OOBE_NameTemplate $APDPDeviceNameTemplate $APDPVariables
    else {
        write-host `t"Autopilot Deployment Profile does not exist. It will be created" -ForegroundColor red
        $APProfile = New-AutopilotProfile -mode UserDrivenAAD -displayName "$APDPDisplayName" -Description "$APDPDescription" -OOBE_Language "os-default" -OOBE_HideEULA -OOBE_HidePrivacySettings -OOBE_NameTemplate "$APDPDeviceNameTemplate" -OOBE_HideChangeAccountOpts -ConvertDeviceToAutopilot -OOBE_EnableWhiteGlove
        # Assigning Group to AutoPilot Profile
        $DynamicDeviceGroup = Get-AzureADGroup -Filter "DisplayName eq '$GroupDisplayNameAutoPilot'"
        Set-AutopilotProfileAssignedGroup -id $ -groupid $DynamicDeviceGroup.ObjectId

This should give Autopilot deployment profiles like this:

Each deployment profile has a computer name template, and it is assigned to the specified dynamic device group pr. country.

This way the autopilot devices should be added to corresponding security groups based on the group tags, and that way they will be assigned the correct deployment profile.

The Autopilot Deployment profile will assign a defined computer name based on the country code and the serial number for the computer. A list of planned computer names:

Deployment ProfileComputer Name Template

Collect Hardware Hash with Group Tag

We are now at the heart of this blog post. Pr request from my previous post, I will share how I created a menu system that simplifies the process of collecting the hardware hash and ensures that the right choice is made per machine regarding the group tag. This will be a set of scripts/files placed on a USB memory stick used by the IT technician. The files are available from my GitHub repository. The USB stick should have the following content:

_readme.txt contains some simple instructions on use:

The GetAutoPilot.cmd file is my menu system used to select the actual group tag used when collecting the hardware hash.

echo Enabling WinRM
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force


echo Which country will this computer primarily be located?
echo  1 - Sweden
echo  2 - Norway
echo  3 - Denmark
echo  4 - Finland
echo  5 - Deutschland
echo 00 - EXIT
echo 99 - Delete CSV

@set /p userinp=Type the number of your choice: 
@set userinp=%userinp:~0,2%
@if "%userinp%"=="1" goto 1
@if "%userinp%"=="2" goto 2
@if "%userinp%"=="3" goto 3
@if "%userinp%"=="4" goto 4
@if "%userinp%"=="5" goto 5
@if "%userinp%"=="00" goto 00
@if "%userinp%"=="99" goto 99

set grouptag=Device-SE
goto end

set grouptag=Device-NO
goto end

set grouptag=Device-DK
goto end

set grouptag=Device-FI
goto end

set grouptag=Device-DE
goto end

del compHash.csv
goto Start

echo Gathering Azure AD Joined AutoPilot Hash
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command .\Get-WindowsAutoPilotInfo.ps1 -OutputFile .\compHash.csv -append -GroupTag %grouptag%
echo Done!

rem shutdown /s /t 5


Get-WindowsAutoPilotInfo.ps1 is a version of the excellent script from Michael Niehaus of This script does the actual hardware hash harvesting.

When running GetAutoPilot.cmd, this will present a simple menu for collecting the hardware hash with a corresponding group tag.

This will calculate the hardware hash and add it and the corresponding group tag to the CSV file on the USB drive.

You can run the script on several computers and collect information for all computers in one CSV file.

The CSV file can now be uploaded to Autopilot Devices in Intune.

The upload can even be automated by slightly changing the command line in my menu system. Using the latest version of the script Get-WindowsAutoPilotInfo.ps1 and adding the “-online” option, the upload can be done directly from the device. My menu system can easily be updated with this functionality.

An example of direct upload of the hardware hash from a device

If you care for even more automation, you should look at Harm Veenstra‘s blog post covering the Automatic Upload of Windows Autopilot hardware hash to your tenant using Azure App registration. You will have an easy-to-operate solution by combining his contribution with my menu system.

The overall process could be summarized like this:

  1. Hardware hash and Group Tag is easily harvested with my menu system on the device
  2. CSV with hash and group tag is uploaded to Autopilot
  3. Device is added to Azure AD group based on the group tag
  4. Deployment profile is assigned based on the Azure AD group membership
  5. Device is booted and Autopilot is onboarding the device for Azure AD and Intune

Hopefully, this could help someone find new working methods, directly or indirectly. Shared with passion on request!

Published inAutomationIntuneMicrosoft 365PowershellScript

One Comment

  1. This seems to be a very nice solution. What about a autorun.inf for just plugging the usb stick?

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: