Windows 11 Provisioning

The Xenter provisioning script configures a Windows 11 device to corporate baseline and registers it in Windows Autopilot — without requiring a custom Windows ISO. It runs directly on the bare Windows install, either during the Out-of-Box Experience (OOBE) on a new laptop or on an existing device already issued to a user. When the script finishes, the device has a standardized name, bloatware removed, BitLocker enabled, and is registered in Autopilot ready for Intune enrollment.

Table of Contents

  1. Quick Start
  2. Prerequisites
  3. Preparing the USB Drive
  4. Provisioning a New Laptop (OOBE)
  5. Provisioning an Existing Device
  6. What the Script Does
  7. Authentication Modes
  8. Post-Provisioning Steps
  9. Configuration Reference
  10. Troubleshooting

Quick Start

New laptop (OOBE)

  1. Prepare the USB drive with a configured .env file (see Preparing the USB Drive).

  2. Power on the laptop and wait for the OOBE language/region screen.

  3. Press Shift+F10 to open an admin command prompt.

  4. Insert the USB drive and navigate to the provisioning folder (adjust drive letter as needed):

    D:
    cd windows-provisioning
    Provisioning.bat
  5. Select the device type when prompted (Laptop, SharedDesktop, or ConferenceRoom).

  6. If using Device Code Flow: visit https://microsoft.com/devicelogin on another device and enter the displayed code.

  7. When the summary appears, record the BitLocker recovery key shown in red.

  8. Remove the USB drive and proceed to Post-Provisioning Steps.

Existing device

  1. Sign in with a local or domain admin account.

  2. Insert the USB drive.

  3. Open an elevated command prompt and run:

    D:
    cd windows-provisioning
    Provisioning.bat
  4. Follow the same prompts as above.

  5. Reboot — the computer rename takes effect on restart.


Prerequisites

Hardware

  • Secure Boot enabled in UEFI/BIOS
  • TPM 2.0 present and enabled (script exits immediately if missing)
  • Wired ethernet connection (Wi-Fi is unreliable during OOBE)

USB Drive

The USB must contain the provisioning files in the correct layout. See Preparing the USB Drive.

Azure AD App Registration

The script uses two Microsoft Graph API calls during provisioning: one to check for duplicate device names and one to upload the Autopilot hardware hash. This requires an App Registration in your tenant with the following permissions granted with admin consent:

Permission Type Purpose
Device.Read.All Application or Delegated Device name conflict check
DeviceManagementServiceConfig.ReadWrite.All Application or Delegated Autopilot hardware hash upload

See the Authentication Modes section and the Azure AD App Registration Setup guide for full setup instructions.

.env File

At minimum, TENANT_ID and CLIENT_ID must be set in the .env file at the USB root before running the script. See Configuration Reference for all available variables.


Preparing the USB Drive

File Layout

The USB should contain the following structure (clone or download the repository to the drive):

D:\windows-provisioning\
├── Provisioning.bat          ← run this
├── .env                      ← your environment config
├── src\
│   ├── Start-XenterProvision.ps1
│   ├── wifi-profile.xml      (optional)
│   └── assets\
│       ├── wallpaper.jpg     (required)
│       └── lockscreen.jpg    (optional)
File Required Notes
Provisioning.bat Yes Entry point — always run this, not the .ps1 directly
src\Start-XenterProvision.ps1 Yes Main provisioning script
.env Yes Must contain at minimum TENANT_ID and CLIENT_ID
src\assets\wallpaper.jpg Yes Corporate desktop wallpaper
src\assets\lockscreen.jpg No Falls back to wallpaper if absent
src\wifi-profile.xml No Corporate Wi-Fi profile; injected if present

Creating the .env File

Create a plain text file named .env at the USB root (alongside Provisioning.bat). At minimum:

TENANT_ID=<Directory (tenant) ID from Entra ID Overview>
CLIENT_ID=<Application (client) ID from App Registration Overview>
CLIENT_SECRET=<client secret value>

Leave CLIENT_SECRET blank or omit it entirely to use Device Code Flow (interactive sign-in). See Authentication Modes.

For additional variables (org name, support contact, timezone, etc.), see the Configuration Reference.

Adding the Corporate Wi-Fi Profile (Optional)

If you want the script to inject the corporate Wi-Fi profile so the device can connect after OOBE, export the profile from a machine already connected to the network:

netsh wlan export profile name="YourSSID" key=clear folder=C:\Temp

Copy the resulting .xml file to src\wifi-profile.xml on the USB. The script injects it system-wide before first user login.


Provisioning a New Laptop (OOBE)

This is the primary use case — provisioning a laptop fresh out of the box without needing a custom Windows ISO.

  1. Power on the laptop and wait until the OOBE language/region selection screen appears. Do not proceed through OOBE setup.

  2. Press Shift+F10. An administrator command prompt opens.

  3. Insert the USB drive. Identify the drive letter Windows assigned to it (check with wmic logicaldisk get caption if unsure — it is typically D: or E:).

  4. Navigate to the provisioning folder and run the script:

    D:
    cd windows-provisioning
    Provisioning.bat
  5. The script displays the Xenter banner and begins the firmware check. If Secure Boot or TPM 2.0 is not detected, the script exits with instructions to enable them in UEFI/BIOS before re-running.

  6. Device type: When prompted, select the device type. This becomes the Autopilot group tag used for dynamic Entra ID group assignment:

    • 1 — Laptop
    • 2 — SharedDesktop
    • 3 — ConferenceRoom
  7. Authentication: Depending on how your .env is configured, one of the following occurs:

    • Client Credentials (silent): Authentication completes automatically with no user action.
    • Device Code Flow: The script displays a URL and a short code. On another device, open a browser, go to https://microsoft.com/devicelogin, and enter the code. Sign in with a Global Administrator or Intune Administrator account. The provisioning script continues automatically once authentication succeeds.
  8. The script runs through all provisioning steps (see What the Script Does). This typically takes 5–10 minutes depending on network speed.

  9. When the summary screen appears, record the BitLocker recovery key displayed in red. Store it securely. It will also be automatically escrowed to Entra ID after the user completes Intune enrollment.

  10. Press Enter to close the script. Remove the USB drive.

  11. The device is now ready for handoff. The OOBE screen is still showing — do not complete setup yourself. Instead, proceed to Post-Provisioning Steps and have the user sign in with their Microsoft 365 credentials to trigger Autopilot enrollment.


Provisioning an Existing Device

The provisioning script is idempotent — it is safe to run on a device that is already in use. This is useful for bringing computers into alignment with the current corporate baseline or re-registering a device in Autopilot after a rebuild.

  1. Sign in to the device with a local or domain administrator account.

  2. Insert the USB drive.

  3. Open an elevated command prompt (Run as administrator) and run:

    D:
    cd windows-provisioning
    Provisioning.bat
  4. Follow the same interactive prompts as the OOBE flow (device type, authentication).

  5. After the script completes, reboot the device. The computer rename (XMD-<serial>) does not take effect until restart.

  6. Verify the device appears in Intune Admin Center > Devices > Windows Autopilot Devices with the correct serial number.

What gets re-applied vs. skipped on an existing device:

Step Behavior
Computer name Skipped if already set correctly
BitLocker Skipped if already enabled
Bloatware removal Re-runs and removes any remaining matches
Wallpaper Re-applied
Autopilot registration Re-runs; no error if already registered

What the Script Does

The script runs 17 provisioning steps in strict order. Steps are grouped below by phase.

Firmware Validation

The very first step checks that the device meets hardware requirements. If either check fails, the script exits immediately with instructions to enable the missing feature in UEFI/BIOS.

  • Secure Boot — Verified via WMI cmdlet with a registry fallback for environments where the cmdlet is unavailable during OOBE.
  • TPM 2.0 — Verified via Get-Tpm.

Identity and Authentication

  1. Serial number — Read from BIOS via Win32_BIOS. If the BIOS serial is missing or a generic placeholder (e.g., To Be Filled By O.E.M.), the script prompts IT to enter it manually.
  2. Device type selection — The IT admin selects Laptop, SharedDesktop, or ConferenceRoom. This becomes the Autopilot group tag, which drives dynamic Entra ID group membership and profile assignment. Skipped if GROUP_TAG is set in .env.
  3. Network check — Pings 8.8.8.8 and microsoft.com. Network-dependent steps are skipped gracefully if no connection is found.
  4. Prerequisites — Installs the NuGet provider and the Get-WindowsAutopilotInfo module from PSGallery (used as an Autopilot registration fallback method).
  5. Azure AD authentication — Obtains a Graph API access token using Client Credentials or Device Code Flow. See Authentication Modes.

Device Configuration

  1. Device name conflict check — Uses the Graph API to verify that XMD-<serial> does not already exist in Azure AD. If a conflict is found, the script asks whether to override or abort.
  2. Computer name — Renames the device to XMD-<serial> (truncated to 15 characters for NetBIOS compatibility). Takes effect after reboot.
  3. Timezone — Sets the system timezone (default: Mountain Standard Time, configurable via .env).
  4. Bloatware removal — Removes AppX packages matching ~30 patterns covering OEM software (Dell, HP, Lenovo), gaming apps, antivirus trials, and Microsoft consumer apps. Also removes provisioned packages so they do not reinstall on new user profiles.
  5. Company Portal — Installs the Microsoft Intune Company Portal via winget. If offline, Company Portal is deployed via Intune after enrollment instead.
  6. Wi-Fi profile — If src\wifi-profile.xml exists on the USB, injects it system-wide via netsh wlan add profile.
  7. Corporate wallpaper — Deploys the wallpaper using PersonalizationCSP and seeds the Default User registry hive so all new profiles inherit it. Stored at C:\Windows\Web\Wallpaper\Xenter\.
  8. OEM support info — Writes support contact information to the registry, visible under Settings > System > About.

Security

  1. BitLocker — Enables BitLocker with XTS-AES 256 encryption using a TPM + Recovery Password protector. The recovery key is displayed in red in the summary and written to the device provisioning log at C:\ProgramData\Xenter\Provisioning\. Record this key. Automatic escrow to Entra ID happens after Intune enrollment.

Autopilot Registration

  1. Hardware hash upload — Uploads the device’s hardware hash to Windows Autopilot via the Graph API with the selected group tag. If the Graph upload fails, the script retries using the Get-WindowsAutopilotInfo cmdlet as a fallback. If the device is already registered, the step is treated as successful.

Summary

  1. Summary display — Shows the final provisioning report: computer name, serial number, BitLocker recovery key (if not yet escrowed), Autopilot registration status, any warnings, and next steps.

Authentication Modes

The script supports two ways to authenticate to Azure AD. Configure your preferred mode in the .env file before deploying the USB.

Device Code Flow (Interactive)

Leave CLIENT_SECRET blank or omit it from .env. The script displays a short code and the URL https://microsoft.com/devicelogin. Sign in on any other device (phone, another laptop) with a Global Administrator or Intune Administrator account.

# CLIENT_SECRET not set — Device Code Flow will be used

Best for: Environments that prefer not to store a client secret on a USB drive.

Requirement: The App Registration must have Delegated permissions with admin consent, and Allow public client flows must be set to Yes under the app’s Authentication settings.

Note: The device code expires after approximately 15 minutes. If it times out before sign-in completes, re-run Provisioning.bat.


Post-Provisioning Steps

After the script finishes and you have recorded the BitLocker key:

  1. Confirm Autopilot registration. In the Intune Admin Center, go to Devices > Enroll devices > Windows Autopilot Devices and search for the device’s serial number. Allow up to 15 minutes for the hash to sync if it was just uploaded.

  2. Assign the device to the user. In the Intune Admin Center, navigate to Devices > All devices, find the device, and assign it to the new hire’s user account. This links Autopilot enrollment to the correct user.

  3. Hand off to the user. The new hire powers on (or continues from the OOBE screen) and signs in with their Microsoft 365 credentials (name@xenter.io). Windows Autopilot runs automatically:

    • Applies the Autopilot deployment profile
    • Enrolls the device in Intune MDM
    • Intune deploys apps, policies, and certificates
    • Company Portal installs assigned apps
    • BitLocker recovery key is automatically escrowed to Entra ID
  4. Verify BitLocker escrow. After enrollment, confirm the recovery key appears in Entra ID: Devices > All devices > [device name] > Recovery keys.

  5. Verify device compliance. In the Intune Admin Center, confirm the device shows as Compliant under its compliance policies after the user completes setup.


Configuration Reference

All variables are set in the .env file at the USB root (next to Provisioning.bat). Lines beginning with # are comments and are ignored.

# Example .env
TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
CLIENT_SECRET=your-secret-value
Variable Required Default Description
TENANT_ID Yes (none) Azure AD Directory (tenant) ID — found on the Entra ID Overview page
CLIENT_ID Yes (none) App Registration Application (client) ID
CLIENT_SECRET No (none) Client secret for silent auth; omit to use Device Code Flow
GROUP_TAG No (interactive prompt) Autopilot group tag; omit to prompt the technician at runtime
ORG_NAME No Xenter, Inc. Full organization name (used in OEM support info)
ORG_SHORT No Xenter Short org name
COMPUTER_PREFIX No XMD Prefix for computer names — result is PREFIX-<serial>
TIMEZONE No Mountain Standard Time Windows timezone string (use Get-TimeZone -ListAvailable to find valid values)
SUPPORT_PHONE No (blank) IT support phone number shown in Settings > System > About
SUPPORT_HOURS No (blank) Support hours shown in Settings > System > About
SUPPORT_URL No (blank) Support URL shown in Settings > System > About
LOG_LEVEL No Information Minimum severity written to the device log. Accepts: Trace, Debug, Information, Warning, Error, Critical

Troubleshooting

Script won’t run / “not digitally signed” error

Always run via Provisioning.bat, not by double-clicking the .ps1 directly. The batch file passes -ExecutionPolicy Bypass for the session so unsigned scripts are allowed.

Firmware requirements check failed (Secure Boot / TPM)

The script exits immediately if Secure Boot or TPM 2.0 cannot be confirmed.

  1. Shut down the device.
  2. Enter UEFI/BIOS setup (key varies by manufacturer: F2, F12, Delete, etc.).
  3. Enable Secure Boot (usually under Boot Security or Security settings).
  4. Enable TPM 2.0 (may appear as PTT on Intel systems or fTPM on AMD systems).
  5. Save and exit, then re-run Provisioning.bat.

Network not detected

The script gates all Azure AD and Autopilot operations on network connectivity. If no network is found, those steps are skipped and the script continues with local-only tasks (naming, bloatware removal, wallpaper, etc.).

During OOBE, use a wired ethernet connection. Wi-Fi is unreliable before a user profile exists. If ethernet is not available, complete local provisioning first, then run the script again from the desktop once connected.

Device Code Flow times out

The device code is valid for approximately 15 minutes. If it expires before sign-in completes, re-run Provisioning.bat. Ensure ethernet is connected before starting and have the sign-in device ready before launching the script.

Device name conflict found

If XMD-<serial> already exists in Azure AD, the script displays the existing device’s object ID and asks whether to continue. Enter y to override (this may create a duplicate device object) or N to abort and investigate in Intune Admin Center > Devices first.

BIOS serial number missing or generic

If the BIOS reports a missing or placeholder serial (e.g., To Be Filled By O.E.M.), the script prompts you to enter one manually. Check the physical label on the device chassis or in the BIOS/UEFI System Information screen. Enter the serial exactly as shown — the script strips special characters automatically.

Autopilot registration fails

Confirm ethernet is connected and retry. If the hash still fails to upload after re-running the script, you can register manually once the device is at the Windows desktop:

$env:Path += ";C:\Program Files\WindowsPowerShell\Scripts"
Get-WindowsAutopilotInfo -Online

Device is already in Autopilot

If the device’s serial number is already registered, the script treats this as a successful registration and continues normally. To verify the existing registration: Intune Admin Center > Devices > Enroll devices > Windows Autopilot Devices — search for the serial number.

BitLocker key not escrowed after provisioning

This is expected. Before Intune enrollment, the device object does not exist in Azure AD, so automatic escrow cannot complete. The recovery key is printed in the provisioning summary and written to C:\ProgramData\Xenter\Provisioning\provision-<serial>.log. Intune’s BitLocker policy escrows the key automatically once the user signs in and completes enrollment. Verify afterwards under: Intune Admin Center > Devices > [device name] > Recovery keys.

Wallpaper not applied after enrollment

PersonalizationCSP may require a sign-out and sign-in to take effect. If the wallpaper does not appear after first login, ask the user to sign out and sign back in.