Oct 23 2023 05:36 AM
As the title says, I want to use a command to customize the group tags of many AutoPilot devices. However, I don't want to use a file as a basis first, as described in many tutorials, but access directly the AutoPilot devices in Intune.
In other words, change all devices with a group tag named "A" to a new tag named "B".
Do you guys have a solution on how I can do this? I've only read something about the Graph API so far?
Thanks a lot!
Oct 23 2023 06:26 AM
That's possible. Check out Bulk Update Windows Autopilot entities (github.com) for more info.
Feb 06 2024 01:38 AM - edited Feb 06 2024 01:38 AM
I found this method stopped working for me around the end of September 2023. Before that it worked fine for me to use a script to automatically add Group Tags to Autopilot devices in Intune based on their on-prem AD OU placement.
I am happy to share the full script I was using that has stopped working if anyone is interested. I have reached out to the author of the original script to see if he has any ideas. I think personally that some Beta feature of the previous MSGraph scripting has been changed and no longer works as it used to.
I have also attempted to use the PowerShell module https://www.powershellgallery.com/packages/WindowsAutoPilotIntune/5.6
but that also has no success at least how I have tried when using MSGraph direct login (without registered app ID and secret etc.).
If anyone has any help to offer I would be most grateful as I do this type of thing many times whilst working as a contract senior IT technician for many different companies on the same cloud enabled Hybrid-Join journey.
Feb 06 2024 01:45 AM
# GroupTagBulkListWinAutopilotDevices-v4.ps1
# Run this script with local admin rights, preferably on a Windows server.
CLS
$ErrorActionPreference = "SilentlyContinue"
## Trust scripts downloaded from the PSGallery
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
## Update Nuget Package and PowerShellGet Module
Install-PackageProvider NuGet -Scope CurrentUser -Force
# Install the required PowerShellGet module if not already installed
if (-not (Get-Module -ListAvailable -Name PowerShellGet)) {
Install-Module PowerShellGet -Scope CurrentUser -Force -AllowClobber
}
## Remove old modules from existing session
Remove-Module PowerShellGet,PackageManagement -Force -ErrorAction Ignore
## Import updated module
Import-Module PowerShellGet -MinimumVersion 2.0 -Force
Import-PackageProvider PowerShellGet -MinimumVersion 2.0 -Force
## MSAL is used with a registered MsalClientApplication in Azure for MSGraph Authentication and requires a -ClientId and -ClientSecret or Certificate
## See https://github.com/AzureAD/MSAL.PS
# Install the required MSAL.PS module if not already installed (Not supported by Microsoft)
if (-not (Get-Module -ListAvailable -Name "MSAL.PS")) {
Install-Module -Name "MSAL.PS" -SkipPublisherCheck -Force -AllowClobber
}
# Install the required AzureAD module if not already installed
if (-not (Get-Module -ListAvailable -Name AzureAD)) {
Install-Module -Name AzureAD -Force -AllowClobber
}
# Install the required Graph.Intune module if not already installed
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph.Intune)) {
Install-Module -Name Microsoft.Graph.Intune -Force -AllowClobber
}
# Check if the OS is a client version
$isClientOS = (Get-CimInstance Win32_OperatingSystem).ProductType -eq 1
# If it is a client OS
if ($isClientOS) {
# Check if RSAT is installed for Windows 10 or 11 client OS
$feature = Get-WindowsCapability -Online | Where-Object { $_.Name -like 'Rsat*' }
if ($feature.Count -gt 0 -and $feature[0].State -ne 'Installed') {
# Install RSAT tools
Add-WindowsCapability -Online -Name $feature[0].Name
}
}
# If it is not a client OS
if (-not $isClientOS) {
# Check if RSAT-AD-PowerShell feature is installed (ONLY WORKS ON SERVER OS)
$featureInstalled = Get-WindowsFeature RSAT-AD-PowerShell -ErrorAction SilentlyContinue
# If not installed, install the feature (ONLY WORKS ON SERVER OS)
if ($featureInstalled -eq $null) {
Install-WindowsFeature RSAT-AD-PowerShell -IncludeAllSubFeature -IncludeManagementTools
}
}
# Install the required ActiveDirectory module if not already installed
if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) {
Install-Module -Name ActiveDirectory -Force -AllowClobber
}
# Install the required WindowsAutoPilotIntune module if not already installed
if (-not (Get-Module -ListAvailable -Name WindowsAutoPilotIntune)) {
Install-Module -Name WindowsAutoPilotIntune -Force -AllowClobber
}
## Import Modules that are not loaded for the current session
# Check if AzureAD module is already imported
if (-not (Get-Module -Name AzureAD -ListAvailable)) {
Import-Module -Name AzureAD -Force
}
# Check if ActiveDirectory module is already imported
if (-not (Get-Module -Name ActiveDirectory -ListAvailable)) {
Import-Module -Name ActiveDirectory -Force
}
# Check if WindowsAutoPilotIntune module is already imported
if (-not (Get-Module -Name WindowsAutoPilotIntune -ListAvailable)) {
Import-Module -Name WindowsAutoPilotIntune -Force
}
# Check if Microsoft.Graph.Intune module is already imported
if (-not (Get-Module -Name Microsoft.Graph.Intune -ListAvailable)) {
Import-Module -Name Microsoft.Graph.Intune -Force
}
Connect-MSGraph
Update-MSGraphEnvironment -SchemaVersion "Beta" -Quiet
# Set-MgEnvironment -GraphEndpoint "https://graph.microsoft.com/v1.0" -SchemaVersion "beta"
Connect-MSGraph -Quiet
CLS
# Define parameters for AD retrieval of computer objects from an OU so that they can be tagged the same.
# $OUpath = 'OU=HybridJoin,OU=Laptop,OU=Workstations,OU=Contoso,DC=com'
# $GrpTag = "Ltop"
# $OUpath = 'OU=HybridJoin,OU=Conference,OU=Workstations,OU=Contoso,DC=com'
# $GrpTag = "Conf"
$OUpath = 'OU=HybridJoin,OU=Desktop,OU=Workstations,OU=Contoso,DC=com'
$GrpTag = "Dtop"
$ExportPath = 'c:\temp\computers_in_ou.csv'
Get-ADComputer -Filter * -SearchBase $OUpath | Select-object Name | Export-Csv -NoType $ExportPath -Force
# Define the input file path
$InputFilePath = 'c:\temp\computers_in_ou.csv'
# Fetch all devices from Intune
$intuneDevices = Invoke-MSGraphRequest -HttpMethod GET -Url "deviceManagement/managedDevices" | Get-MSGraphAllPages
# Load computer names from the input file
$computerNames = Get-Content -Path $InputFilePath
# Define an array to store results
$results = @()
foreach ($computer in $computerNames) {
Write-Output "=============================================================================="
Write-Output "A Computer was found named: $computer"
$PC = $computer.Trim('"')
# Find a matching device in Intune based on computer name
Write-Output "Trying to match " $_.deviceName " and $PC"
$matchedDevice = $intuneDevices | Where-Object { $_.deviceName -eq $PC }
if (-not $matchedDevice) {
Write-Output "Matching Failed"
}
if ($matchedDevice) {
Write-Output "Matching Success"
$results += [PSCustomObject]@{
ComputerName = $PC
SerialNumber = $matchedDevice.serialNumber
}
$computerSerial = $matchedDevice.serialNumber
Write-Output "SN: $computerSerial"
# Get all autopilot devices for Invoke-MSGraphRequest method
$autopilotDevices = Invoke-MSGraphRequest -HttpMethod GET -Url "deviceManagement/windowsAutopilotDeviceIdentities" | Get-MSGraphAllPages
# Single out the autopilot device we are dealing with that has a name matching the serial number of the Intune/AD device.
$matchedDevice2 = $autopilotDevices | Where-Object { $_.serialNumber -eq $computerSerial }
if ($matchedDevice2) {
$matchedDevice2.groupTag = $GrpTag
# Request Body required for Invoke-MSGraphRequest parameter.
$requestBody = @"
{
groupTag: "`"$($matchedDevice2.groupTag)`"",
}
"@
# Quoted Group Tag required for Set-AutopilotDevice command parameter.
$QuotedGrpTag = '"' + $GrpTag + '"'
Write-Output "Updating entity: $($matchedDevice2.id) | groupTag: $($matchedDevice2.groupTag)"
# Attempt 2 different methods to set the Group Tag for the Serial Number Autopilot object
Set-AutopilotDevice -id $computerSerial -groupTag $QuotedGrpTag
Invoke-MSGraphRequest -HttpMethod POST -Content $requestBody -Url "deviceManagement/windowsAutopilotDeviceIdentities/$($matchedDevice2.id)/UpdateDeviceProperties"
}
}
}
# Invoke an autopilot service sync
Invoke-MSGraphRequest -HttpMethod POST -Url "deviceManagement/windowsAutopilotSettings/sync"
# Remove all values from used variables
$OUpath = $null
$GrpTag = $null
$QuotedGrpTag = $null
$ExportPath = $null
$InputFilePath = $null
$intuneDevices = $null
$computerNames = $null
$results = $null
$computer = $null
$PC = $null
$matchedDevice = $null
$computerSerial = $null
$autopilotDevices = $null
$matchedDevice2 = $null
$requestBody = $null
# Delete the input file
Remove-Item -Path $InputFilePath -Force
Aug 15 2024 03:12 AM
RESOLVED August 2024
So, This method involves first publishing Microsoft Graph PowerShell as an enterprise app in your AzureAD, and granting your admin account access to it... Then using the following PowerShell scripts you can either set Autopilot device objects with a new GroupTag by replacing an existing GroupTag, or Bulk Update Autopilot device objects with a new GroupTag using a list of serial numbers from a file (you can export all the Autopilot device objects from Intune to get all the SNs).
I pulled the original for these 2 scripts from GitHub here: https://github.com/stevecapacity/IntunePowershell/blob/main/Autopilot%20Helper%20Scripts/bulkGroupTa... all credit to SteveCapacity for pointing me in the right direction although his script left something to be desired as it produced errors out of the box.
########################################################################################################################################################
# GroupTagBulkChangeWinAutopilotDevices.ps1
# Bulk Update Autopilot device objects with a new GroupTag by replacing an existing GroupTag
# Autopilot device object old GroupTag to be changed
$autopilotOldTag = "Ltop"
# New GroupTag to change if the Autopilot device object has the old GroupTag
$autopilotNewTag = "LAPTOP"
# install autopilot module
$nuget = Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction Ignore
if(-not($nuget))
{
Install-PackageProvider -Name NuGet -confirm:$false -Force
Write-Host "Installed NuGet"
}
else
{
Write-Host "NuGet already installed"
}
$module = Get-Module -ListAvailable -Name WindowsAutopilotIntune -ErrorAction Ignore
if(-not($module))
{
Install-Module -Name WindowsAutopilotIntune -confirm:$false -Force
Write-Host "Installed WindowsAutopilotIntune"
}
else
{
Write-Host "WindowsAutopilotIntune already installed"
}
# Disconnect from microsoft graph in case session connect to a previous tenant still valid
Disconnect-MgGraph
# connect to microsoft graph
Connect-MgGraph -scopes "Group.ReadWrite.All, Device.ReadWrite.All, DeviceManagementManagedDevices.ReadWrite.All, DeviceManagementServiceConfig.ReadWrite.All, GroupMember.ReadWrite.All"
# You can change the group tag of autopilot devices using an old group tag as a target
# Get every existing Autopilot device object
$autopilotDevices = Get-AutopilotDevice
# for each autopilot device, get the entra device object serial number, id, and grouptag
foreach ($autopilotDevice in $autopilotDevices) {
try
{
$autoPilotSN = $autopilotDevice.serialNumber
$autoPilotid = $autopilotDevice.id
$autoPilotgrpTag = $autopilotDevice.groupTag
# Compare the existing tag with the OldTag to be changed
if ($autoPilotgrpTag -eq $autopilotOldTag) {
# Perform the command if they are the same
Write-Host "The tags match for Autopilot device object $autoPilotSN - Change this to the new tag."
Set-AutopilotDevice -id $autoPilotid -GroupTag $autopilotNewTag
Write-Host "Changed group tag for device with serial number $autoPilotSN"
}
else {
Write-Host "The values are different for device with serial number $($autoPilotSN). No change made."
}
}
catch
{
$message = $_.Exception.Message
Write-Host "Failed to change group tag for device with serial number $($autoPilotSN): $message"
}
}
########################################################################################################################################################
And here is the method of updating all the GroupTags using an input file list of Serial Numbers.
########################################################################################################################################################
# GroupTagBulkListWinAutopilotDevices.ps1
# Bulk Update Autopilot device objects with a new GroupTag using a list of serial numbers from a file
# CSV file path - format the .csv file with the top line reading SerialNumber and each subsequent line having a unique machine serial number on it only- E.G. (without the hash tag comment symbol)
# SerialNumber
# SN0123456
# SN2345678
# SN3456789
$csvFile = "C:\TEMP\Dtop.csv"
# New GroupTag to place on the Autopilot device object
$autoPilotGroupTag = "DESKTOP"
# install autopilot module
$nuget = Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction Ignore
if(-not($nuget))
{
Install-PackageProvider -Name NuGet -confirm:$false -Force
Write-Host "Installed NuGet"
}
else
{
Write-Host "NuGet already installed"
}
$module = Get-Module -ListAvailable -Name WindowsAutopilotIntune -ErrorAction Ignore
if(-not($module))
{
Install-Module -Name WindowsAutopilotIntune -confirm:$false -Force
Write-Host "Installed WindowsAutopilotIntune"
}
else
{
Write-Host "WindowsAutopilotIntune already installed"
}
# Disconnect from microsoft graph in case session connect to a previous tenant still valid
Disconnect-MgGraph
# connect to microsoft graph
Connect-MgGraph -scopes "Group.ReadWrite.All, Device.ReadWrite.All, DeviceManagementManagedDevices.ReadWrite.All, DeviceManagementServiceConfig.ReadWrite.All, GroupMember.ReadWrite.All"
# You can change the group tag of autopilot devices using either a list of serial numbers or using an old group tag as a target
# Change group tag using a list of serial numbers
# get list of serial numbers from CSV file
$serialNumbers = Import-Csv -Path $csvFile | Select-Object -ExpandProperty SerialNumber
# for each serial number, get entra device object id
foreach ($serialNumber in $serialNumbers) {
try
{
$id = (Get-AutopilotDevice -serial $serialNumber).id
Set-AutopilotDevice -id $id -GroupTag $autoPilotGroupTag
Write-Host "Changed group tag for device with serial number $serialNumber"
}
catch
{
$message = $_.Exception.Message
Write-Host "Failed to change group tag for device with serial number $($serialNumber): $message"
}
}
# Autopilot device object old GroupTag to be changed
$autopilotOldTag = "Ltop"
# New GroupTag to change if the Autopilot device object has the old GroupTag
$autopilotNewTag = "LAPTOP"
$autopilotDevices = Get-AutopilotDevice
# for each autopilot device, get entra device object serial number, id, and grouptag
foreach ($autopilotDevice in $autopilotDevices) {
try
{
$autoPilotSN = $autopilotDevice.serialNumber
$autoPilotid = $autopilotDevice.id
$autoPilotgrpTag = $autopilotDevice.groupTag
# Compare the existing tag with the OldTag to be changed
if ($autoPilotgrpTag -eq $autopilotOldTag) {
# Perform the command if they are the same
Write-Host "The tags match for Autopilot device object $autoPilotSN - Change this to the new tag."
Set-AutopilotDevice -id $autoPilotid -GroupTag $autopilotNewTag
Write-Host "Changed group tag for device with serial number $autoPilotSN"
}
else {
Write-Host "The values are different."
}
}
catch
{
$message = $_.Exception.Message
Write-Host "Failed to change group tag for device with serial number $($autoPilotSN): $message"
}
}
########################################################################################################################################################