This post describes the actions to create a Windows 10 Autopilot Profile via Powershell. I am always trying to automate as much as possible to reduce repeating actions. Now it is time to automate my Windows 10 Autopilot deployment.
Firstly, I need to make a shoutout to Rudy Ooms and his blog (Call4Cloud). I got the idea from him and used a piece of his code. You can find the basis for a full Windows 10 Autopilot deployment in this Github repo. This is for advanced Powershell and Graph API users.
Damien Van Robaeys helped make this script even more efficient. Shoutout to you too!
I explain, in a detailed manner, how you can create your Windows 10 Autopilot Profile via Powershell.
Now there is only 1 step involved. Run the script below.
Create Dynamic Group, an Autopilot Profile and Assign the profile
Firstly, save this code a .ps1 file:
param ( [Parameter(Mandatory=$true)] [string]$DynamicGroupName, [Parameter(Mandatory=$true)] [string]$OrderID, [Parameter(Mandatory=$true)] [string]$AutopilotProfileName ) # *************************************************************************************** # Check for module part # *************************************************************************************** #Checking for correct modules and installing them if needed $InstalledModules = Get-InstalledModule $Module_Name = "MSAL.PS" If ($InstalledModules.name -notcontains $Module_Name) { Write-Host "Installing module $Module_Name" Install-Module $Module_Name -Force } Else { Write-Host "$Module_Name Module already installed" } #Importing Module Write-Host "Importing Module $Module_Name" Import-Module $Module_Name # *************************************************************************************** # Authentication part # *************************************************************************************** #Connecting to Azure AD to Create the Group # Write-Host "Connecting to Azure AD, fill the credential prompt" $myToken = Get-MsalToken -ClientId d1ddf0e4-d672-4dae-b554-9d5bdfd93547 -RedirectUri "urn:ietf:wg:oauth:2.0:oob" -Interactive # *************************************************************************************** # Create group part # *************************************************************************************** ##DynamicGroupRule Properties: $DynamicGroupRule = "(device.devicePhysicalIds -any _ -eq ""[OrderID]:$OrderID"")" # Creating group $Group_URL = "https://graph.microsoft.com/beta/groups/" $group = @{ "displayName" = $DynamicGroupName; "description" = "This is used Windows 10 Autopilot Device with the OrderID $OrderID"; "groupTypes" = @("DynamicMembership"); "mailEnabled" = $False; "mailNickname" = "AutoPilotGroup-$OrderID"; "membershipRule" = $DynamicGroupRule; "membershipRuleProcessingState" = "On"; "securityEnabled" = $True } $requestBody = $group | ConvertTo-Json #-Depth 5 $Create_group = Invoke-RestMethod -Headers @{Authorization = "Bearer $($myToken.AccessToken)" } -Uri $Group_URL -Method POST -Body $requestBody -ContentType 'application/json' $Group_ID = $Create_group.id # Write-Host "Group created! Save this Object ID: $($CreateDynamicGroup.Id) in a notepad for later use" -ForegroundColor Green Write-Host "Group created: $Group_ID!" -ForegroundColor Green # *************************************************************************************** # Create profile part # *************************************************************************************** $AutopilotProfileDescription = "$AutopilotProfileName Azure AD Join AutoPilot Profile" $Profile_Body = @{ "@odata.type" = "#microsoft.graph.azureADWindowsAutopilotDeploymentProfile" displayName = "$($AutopilotProfileName)" description = "$($AutopilotProfileDescription)" language = 'os-default' extractHardwareHash = $false enableWhiteGlove = $true outOfBoxExperienceSettings = @{ "@odata.type" = "microsoft.graph.outOfBoxExperienceSettings" hidePrivacySettings = $true hideEULA = $true userType = 'Standard' deviceUsageType = 'singleuser' skipKeyboardSelectionPage = $false hideEscapeLink = $true } enrollmentStatusScreenSettings = @{ '@odata.type' = "microsoft.graph.windowsEnrollmentStatusScreenSettings" hideInstallationProgress = $true allowDeviceUseBeforeProfileAndAppInstallComplete = $true blockDeviceSetupRetryByUser = $false allowLogCollectionOnInstallFailure = $true customErrorMessage = "An error has occured. Please contact your IT Administrator" installProgressTimeoutInMinutes = "45" allowDeviceUseOnInstallFailure = $true } } | ConvertTo-Json $Profile_URL = "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles" $Create_Profile = Invoke-RestMethod -Headers @{Authorization = "Bearer $($myToken.AccessToken)" } -Uri $Profile_URL -Method POST -Body $Profile_Body -ContentType 'application/json' $Get_Profile_ID = $Create_Profile.ID # *************************************************************************************** # Assign profile part # *************************************************************************************** $Assignment_Body = @" {"target":{"@odata.type":"#microsoft.graph.groupAssignmentTarget","groupId":"$Group_ID"}} "@ $Profile_Assignment_URL = "$Profile_URL/$($Get_Profile_ID)/assignments" Invoke-RestMethod -Headers @{Authorization = "Bearer $($myToken.AccessToken)" } -Uri $Profile_Assignment_URL -Method POST -Body $Assignment_Body -ContentType 'application/json' Write-Host "ProfilE created and assign to the group!" -ForegroundColor Green
After that, use this code to run the file and add the parameters:
.\Function_Create-AutoPilotDynamicGroup.ps1 -DynamicGroupName NielsKokTech_AutoPilot_Dynamic -OrderID NielsKokTech
As a result, this is shown:

Fill the credential prompt with an account that has the proper permissions:

After that, this is the output and everything is done!

This is the group created by the script:

Furthermore, this script creates an Azure AD joined Windows 10 Autopilot profile. if you want to edit the properties of the profile, please edit the $Body in the file above.
After that, the Windows 10 Autopilot Profile is created according to the $Body in the Powershell Script:


That’s how you create Windows 10 Autopilot profile and assign it via Powershell.
Other posts
Want to create an Autopilot manually? Check out these posts:
Azure AD Joined profile
Hybrid AD Joined profile
[…] Profile, Dynamic Group, and assigns the dynamic group to the autopilot profile. Check it out here.Run the script to assign the policies using the following […]
I really would love to use that script but I have a problem with -ClientId d1ddf0e4-d672-4dae-b554-9d5bdfd93547, I replace your ClientID with mine but realize I do not have the proper one so it failed can you help me on that part ? What do I need to do or where do I get the right one..
Your help is appreciated.
Hi James,
You don’t need to change the client id. This is a general Intune Powershell App Rep object ID which is the same for each tenant. After that, you should just be able to run the script. Which error are you getting?
Thanks,
Niels
Hi there, it’s a brilliant script, but would love to know how to modify it for Hybrid as per below question ..any ideas ?
Hi Mauberley,
How did you change the script so that the autopilot profile is Join to Azure AD as “Hybrid Azure AD joined” (versus Azure AD joined)
Thanks,
John
Hi John,
Thanks, I have another post on that:
https://www.nielskok.tech/intune/domain-join-profile-intune-via-powershell/
Kind Regards,
Niels
hey Niels,
Thanks for replaying, i did see and use you second link already which created the domain join configuration profile – works fantastic also !
What i was more getting at is this article set’s up the AUTOPILOT profile as join type Azure AD Join
I’m after how to setup the AUTOPILOT profile as join type Hybrid Azure AD joined
hoping that makes sense ?
Thanks,
John
Hi John,
I understand, thanks for elaborating.
You need to edit the script which creates the Azure AD Joined AutoPilot profile to use this parameter set:
$params = @{
“@odata.type” = “#microsoft.graph.activeDirectoryWindowsAutopilotDeploymentProfile”
displayName = “dfsgsdf”
description = “”
deviceNameTemplate = “”
language = “os-default”
enableWhiteGlove = $false
deviceType = “windowsPc”
extractHardwareHash = $false
roleScopeTagIds = @(
)
hybridAzureADJoinSkipConnectivityCheck = $false
outOfBoxExperienceSettings = @{
deviceUsageType = “singleUser”
hideEscapeLink = $true
hidePrivacySettings = $true
hideEULA = $true
userType = “standard”
skipKeyboardSelectionPage = $true
}
}
In stead of the Azure AD Joined parameter set.
I hope you can change it yourself.
if not, let me know.
Thanks,
Niels
Thank you so much Neil (no reply button on the fix script you gave me for some reason) ..so replying here ..
the line microsoft.graph.activeDirectoryWindowsAutopilotDeploymentProfile is the one i needed !!
brilliant!! thank you !!
Hi John,
Lovely to hear 🙂
Thanks for the response.
KR,
Niels
Thank you for this! I have used this with some customizations 🙂
You’re welcome!
This script was helpfull and easy to use for a Powershell dummy like me :). Made some small customizations to include a custom deviceName template into the Create Profile Part.
$DeviceNameTemplate = “$OrderID-%SERIAL%”
deviceNameTemplate = “$($DeviceNameTemplate)”
Running the script works great.
I have one question, I have to create almost 80 Dep Profiles because of the deviceNames that we have per region, company, branch.
i.e. ABC, DEF, XYZ
How can I modify the ps to read the entries from an excel sheet into an array and then to just create the profiles from the input list.
The AADGroup Name = ABC-WindowsAutoPilot
OrderID = ABC
AutoPilotProfileName = ABC
Hi Mario,
Thanks for your e-mail. That is possible but I need to figure out some variables via the Graph. I will update the post with the extra variables later on.
Stay tuned!
Thanks,
Niels
[…] Explorer (Used for looking up the correct JSON body’s)Other posts about Graph:Create Autopilot Profile via PowershellIntune Config Backup to Storage […]
For me the sec group gets created but the script errors out at the “$Create_Profile = Invoke-RestMethod”
________________________
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At C:\******.ps1:*****
+ … e_Profile = Invoke-RestMethod -Headers @{Authorization = “Bearer $($m …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At C:\****************\*********.ps1:****
+ Invoke-RestMethod -Headers @{Authorization = “Bearer $($myToken.Acces …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Any ideas ? It seems to say something wrong with body, but I don’t think so, have checked and colleague also checked.
I read something about it maybe being permissions ?
Hi Mauberley,
I have used this yesterday. Could you maybe try to download the template again?
Since, in my opinion, this should work.
Regards,
Niels
Hi Niels, thanks for your prompty reply, in the meantime I managed to fix it. It was due to me changing the language to a variable. This works, but you have to enter the region code eg ‘fr-FR’ not ‘French (France)’ as it displays in Intune, and not fr-fr either which I also tried (it’s case sensitive).
So all good now ;).
Whilst we’re here, do you know any way to create Device Configuration profiles using PowerShell ? Specifically, the Domain Join config template. We have a lot of companies in our organisation (+150) and we put each one’s clients in a separate OU. Creating the profiles and sec groups using your script was already a great help, but being able to automate the Domain Join Config profile would be next level ;). I’ve had a look at the Powershell commands like Get-IntuneDeviceConfigurationPolicy, but doesn’t seem to be pertinent.
Thanks again.
Hi Mauberley,
Good to hear that things worked out!
That is a nice subject for my next blog. Stay tuned. Will write it probably this week.
Thanks mate,
Niels
That would be most useful and I’m pretty sure not just for me 😉
Hi Mauberley,
I wrote it already! 🙂 https://www.nielskok.tech/intune/domain-join-profile-intune-via-powershell/
Regards,
Niels
Oh and yes I did modify the script above so it creates a Hybrid profile, and that part works fine. I should mention that before any confusion arises from my talking about Domain Join config templates 😉
Hi Mauberley,
How did you change the script so that the autopilot profile is Join to Azure AD as “Hybrid Azure AD joined” (versus Azure AD joined)
Thanks,
John
[…] is a blog post on request. Someone commented on another post (Create Autopilot Profile Powershell) that they would like a script to create a Domain Join Profile in Intune via Powershell. Some of […]
Great work Niels, thank you for sharing with the community! We are working on how to rename Autopilot devices to our company standard naming convention for Hybrid Azure-AD Joined devices. Any sugguestions are insight would be greatly appreciated.
RWells
Hi Rich,
Thanks for your comment. You could look at another post of mine:
https://www.nielskok.tech/intune/domain-join-profile-intune-via-powershell/
This will help you to create an AD Domain Join profile with your naming convention.
If you need help adjusting the script. let me know!
Niels
can you also change the script you do a hybrid join and not an azure ad join?
Hi Jurgen,
I have written a script for this:
https://www.nielskok.tech/intune/domain-join-profile-intune-via-powershell/
Thanks,
Niels
Hello Niels,
I already saw that script but i am looking for a autopilot deployment profile with just the azure ad join changed by the hybrid azure join 🙂
Kind regards,
Jurgen
Hi Jurgen,
I will try to make time for you.
I will let you know.
Niels
LEDGEND!
Saved my life with the Assignment part
Could not get it to work!
Thanks!!!!!!
haha thanks Leon! 🙂
Hi,
I have created a ESP with this command:
$Body = @{
“@odata.type” = “#microsoft.graph.windows10EnrollmentCompletionPageConfiguration”
displayName = “$($EnrollmentPageName)”
description = “$($EnrollmentPageName) Azure AD Join AutoPilot Enrollment Status Page”
deviceEnrollmentConfigurationType = ‘windows10EnrollmentCompletionPageConfiguration’
showInstallationProgress = $true
blockDeviceSetupRetryByUser = $false
allowDeviceResetOnInstallFailure = $true
allowLogCollectionOnInstallFailure = $true
customErrorMessage = “Setup could not be completed. Please try again or contact your support person for help.”
installProgressTimeoutInMinutes = 45
allowDeviceUseOnInstallFailure = $false
allowNonBlockingAppInstallation = $true
installQualityUpdates = $true
trackInstallProgressForAutopilotOnly = $true
disableUserStatusTrackingAfterFirstUser = $true
} | ConvertTo-Json
$URL = “https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations”
$Data = Invoke-RestMethod -Headers @{Authorization = “Bearer $($myToken.AccessToken)” } -Uri $URL -Method POST -Body $Body -ContentType ‘application/json’
It works fine, but how do I assign it to a group?
Hi Liraren,
I haven’t posted about that. Let me check that for you.
Thanks,
Niels