
Timothy Alexander
IT Specialist

Using Microsoft Graph to Integrate AutoPilot into SCCM Task Sequences
In the dynamic landscape of IT, we often find ourselves balancing the old with the new. For many organizations, in my case a school district, this means maneuvering through legacy systems while integrating modern technologies. This post will be about a PowerShell script I used to try and implement AutoPilot the best I could in a mixed environment of SCCM and Intune devices.
The Old: Fat Imaging and Provisioning Packages
For years we had employed 'fat' imaging—preinstalling all necessary applications—for devices and the person who started with Intune (just for our High School student laptops during Covid lockdowns) had the technicians manually applying provisioning packages to the devices with the fat image already applied. The technicians would have to choose either the standard task sequence or one for Intune devices, with the Intune task sequence skipping the ConfigMgr client and rebooting to OOBE.
The first two things I did were get rid of the fat image, having the software install during the task sequence, and merge the two task sequences so it would automatically set the device up for Intune based on the variables set during the UI++ step and apply the provisioning package before rebooting. This had to be walked back a bit because of complaints that the Intune devices were not ready when handed to end users (it needed to install software after the user logged in) and that imaging was taking too long because it was installing software during the task sequence. So I ended up with the task sequences still merged but having to use the fat image still so the task sequence would speed up and Intune devices would have all the basics installed before a user logged in for the first time.
The New: AutoPilot and Clean Imaging
We transitioned all staff laptops, and student laptops at a few more schools, to Intune and I wanted to try and take advantage of AutoPilot again. I had a little more experience and figured it would be easy enough to use the AutoPilot Hash Upload script from a flash drive at OOBE on new devices. I wrote a script that used Windows forms to let the techs set the location and asset number so we could correctly name the device, before uploading the hash and waiting about 6 minutes for the profile to get assigned and finally rebooting. That added too many extra steps though, so I had to find a way to make it work during imaging even though I couldn’t upload the device hash from Windows PE since it doesn’t have access to the right name spaces.
Since we have a pretty large variety of device model, some even being consumer, I couldn’t just check for TPM 2.0 since they might not support attestation (the HP 255 G7 laptops we have are my primary pain point so far with not support attestation). I started by testing all the student model laptops, and since they all worked I added a step to set a variable named TPMSupport to true if it was one of those models; I’ve been adding other models as I get the chance. We are still stuck with the fat image on devices that don’t support self deploy but at least we are moving in the right direction.
To facilitate this transition, I went to PowerShell to streamline the process. This script had a dual function:
1. Check if the device was already registered in the school district's tenant (indicating an AutoPilot profile assignment)
2. Based on this check, install a clean image and boot to OOBE (Out-of-Box Experience) for the device enrollment status page, or apply the fat image and use a provisioning package to join AzureAD with a bulk enrollment token.
Check Out the Script Here

How the Script Works
MS Graph Authentication Variables: The script begins by setting up the Azure AD App authentication credentials, which will be used to establish a connection to Microsoft Graph, a RESTful web API that interfaces with Microsoft 365 services. You would replace the placeholder text with your actual Client ID, Client Secret, and Tenant ID. You will need an app with Intune Read and Write permissions so it can update the device info and initiate the sync.
Environment Setup: It sets up the LOCALAPPDATA environment variable, which is required when the script is running in a system context where this variable might not be set by default. It also defines the working directory as the system's temporary folder.
Module Management: The script ensures that the PowerShellGet (a module manager) and PackageManagement (provides cmdlets for managing PowerShell modules and other package types) are installed on the system. If these modules are not present, they are downloaded and installed. After ensuring these modules are installed, the script imports the PowerShellGet module.
Installing and Importing Necessary Modules: The script installs and imports the necessary modules for working with Windows Autopilot and Intune. These modules include commands and cmdlets for managing these services.
Variable Assignment: Creates a COM object to interact with the Task Sequence environment variables. Several variables are assigned using values from the Task Sequence, which will be used later in the script like the TPMSupport variable, the computer name, and the Autopilot Profile.
Device Serial Number Retrieval: The script attempts to retrieve the serial number of the device using the Windows Management Instrumentation Command-line (WMIC). If the serial number cannot be retrieved, an error is thrown and the 'ProfileAssigned' task sequence environment variable is set to "False".
Connecting to Microsoft Graph: The script then attempts to connect to Microsoft Graph using the provided tenant ID, application ID, and application secret. If the connection fails, an error is thrown and the 'ProfileAssigned' task sequence environment variable is set to "False".
Locating and Updating Device Info: The script attempts to locate the device in the Autopilot service using the retrieved serial number. If the device is found, the script updates the device's information in the Autopilot service and initiates an Autopilot Sync. If the device cannot be located or the update and sync operations fail, an error is thrown and the 'ProfileAssigned' task sequence environment variable is set to "False".
I hope this post has been informative and helpful. If you're facing a similar issue, feel free to use and modify this script to suit your needs. Happy scripting!