Manually register devices with Windows Autopilot

Windows Autopilot device registration can be done within your organization by manually collecting the hardware identity of devices and uploading this information in a comma-separated-value (CSV) file. Capturing the hardware hash for manual registration requires booting the device into Windows 10.

Device owners can only register their devices with a hardware hash. Other methods (PKID, tuple) are available through OEMs or CSP partners.

This article provides step by step guidance to perform manual registration. For an overview of registration and manual registration, see the following topics on docs.microsoft.com:

Important

In Windows 10, version 1809 and earlier, it is important to not connect the device to the Internet prior to capturing the hardware hash. This includes collectiong the hardware hash, uploading the .CSV into MSfb or Intune, and assigning the profile. Connecting the device to the Internet before this process is complete will result in the device downloading a blank profile that is stored on the device until it’s removed.

After Intune reports the profile is ready, only then you can connect the device to the Internet.

Note

If OOBE is restarted too many times, it can enter a recovery mode and fail to run the Autopilot configuration. If OOBE displays multiple configuration options on the same page (language, region, and keyboard layout), then it is in recovery mode. Normally OOBE displays each of these configuration option on a different page.

You can change the HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\UserOOBE value to 1 to ensure OOBE has not been restarted too many times.

Manually register devices with Windows Autopilot
The hardware hash for an existing device is available through Windows Management Instrumentation (WMI), as long as that device is running a supported version of Windows 10 semi-annual channel. You can use a PowerShell script (Get-WindowsAutoPilotInfo.ps1) to get a device’s hardware hash and serial number. The serial number is useful to quickly see which device the hardware hash belongs to.

To use this script you can either download it or install it directly from the Windows PowerShell Gallery. To install it directly and capture the hardware hash, use the following commands from an elevated Windows PowerShell prompt.

New-Item -Type Directory -Path "C:\HWID"
Set-Location -Path "C:\HWID"
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted
Install-Script -Name Get-WindowsAutoPilotInfo
Get-WindowsAutoPilotInfo.ps1 -OutputFile AutoPilotHWID.csv

I personally like to run the script from a USB stick. The collected hardware ID is then also written to this USB stick in the folder named CSV. I use the Windows Powershell script from the gallery which is slightly modified and a CMD file which runs the Windows Powershell script.

@ECHO OFF

PUSHD %~dp0

color 09
ECHO -----------------------------------------------------------------------------
ECHO Collecting Hardware Key
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command "%~dp0\Get-WindowsAutoPilotInfo.ps1" -ComputerName $env:computername -OutputFile "%~dp0\CSV\computers.csv" -append
ECHO -----------------------------------------------------------------------------
Echo Hardware Keys has been uploaded to USB DRIVE

TIMEOUT 5

EXIT 0
[CmdletBinding()]
param(
    [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True,Position=0)][alias("DNSHostName","ComputerName","Computer")] [String[]] $Name = @($env:ComputerName),
    [Parameter(Mandatory=$False)] [String] $OutputFile = "", 
    [Parameter(Mandatory=$False)] [Switch] $Append = $false,
    [Parameter(Mandatory=$False)] [System.Management.Automation.PSCredential] $Credential = $null,
    [Parameter(Mandatory=$False)] [Switch] $Partner = $false,
    [Parameter(Mandatory=$False)] [Switch] $Force = $false
)

Begin
{
    # Initialize empty list
    $computers = @()
}

Process
{
    foreach ($comp in $Name)
    {
        $bad = $false

        # Get the common properties.
        Write-Verbose "Checking $comp"
        $serial = (Get-WmiObject -ComputerName $comp -Credential $Credential -Class Win32_BIOS).SerialNumber

        # Get the hash (if available)
        $devDetail = (Get-WMIObject -ComputerName $comp -Credential $Credential -Namespace root/cimv2/mdm/dmmap -Class MDM_DevDetail_Ext01 -Filter "InstanceID='Ext' AND ParentID='./DevDetail'")
        if ($devDetail -and (-not $Force))
        {
            $hash = $devDetail.DeviceHardwareData
        }
        else
        {
            $bad = $true
            $hash = ""
        }

        # If the hash isn't available, get the make and model
        if ($bad -or $Force)
        {
            $cs = Get-WmiObject -ComputerName $comp -Credential $Credential -Class Win32_ComputerSystem
            $make = $cs.Manufacturer.Trim()
            $model = $cs.Model.Trim()
            if ($Partner)
            {
                $bad = $false
            }
        }
        else
        {
            $make = ""
            $model = ""
        }

        # Getting the PKID is generally problematic for anyone other than OEMs, so let's skip it here
        $product = ""

        # Depending on the format requested, create the necessary object
        if ($Partner)
        {
            # Create a pipeline object
            $c = New-Object psobject -Property @{
                "Device Serial Number" = $serial
                "Windows Product ID" = $product
                "Hardware Hash" = $hash
                "Manufacturer name" = $make
                "Device model" = $model
            }
            # From spec:
            # "Manufacturer Name" = $make
            # "Device Name" = $model

        }
        else
        {
            # Create a pipeline object
            $c = New-Object psobject -Property @{
                "Device Serial Number" = $serial
                "Windows Product ID" = $product
                "Hardware Hash" = $hash
            }
        }

        # Write the object to the pipeline or array
        if ($bad)
        {
            # Report an error when the hash isn't available
            Write-Error -Message "Unable to retrieve device hardware data (hash) from computer $comp" -Category DeviceError
        }
        elseif ($OutputFile -eq "")
        {
            $c
        }
        else
        {
            $computers += $c
        }

    }
}

End
{
    if ($OutputFile -ne "")
    {
        if ($Append)
        {
            if (Test-Path $OutputFile)
            {
                $computers += Import-CSV -Path $OutputFile
            }
        }
        if ($Partner)
        {
            $computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash", "Manufacturer name", "Device model" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
            # From spec:
            # $computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash", "Manufacturer Name", "Device Name" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
        }
        else
        {
            $computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
        }
    }
}

Now that you have captured hardware hashes in a CSV file, you can add Windows Autopilot devices by importing the CSV file(s). The following are instructions to import the CSV using Intune:

  1. In the Microsoft Endpoint Manager admin center, choose Devices > Enroll devices | Windows enrollment > Devices
  1. Under Windows Autopilot devices click import, browse to a CSV file listing the device(s) that you want to add
  1. Choose import to start importing the devices information, it can take up to 15 minutes.
  2. After the import is completed, choose Devices > Enroll devices | Windows enrollment > Devices > Sync. You will see a message that indicates the synchronization is in progress. The process may take several minutes depending on the number of devices imported.
  3. Refresh the view to see the new device(s)

Ideally, this proces is performed by the OEM, reseller, or distributor from which the device(s) were purchased. An OEM or other device provider uses the registration authorization process to perform device registration on your behalf.

You may also like...

10 Responses

  1. Fer says:

    Hi Raymond, thank you for your post.
    I’d like to learn how can I use your script?
    I am newbie at this stage.
    Should I create a folder into USB stick named CSV and save a powershell script and run inside it?
    Thank you anyway

    • Hi Fer, you can create the CMD-file and the PS1–file in the root of the USB-stick. In the root of the USB-stick you can create the CSV folder. When you run the BAT-file in elevated mode the hardware-ID will be exported to the CSV directory.

  2. Dave says:

    Hi Raymond, thanks for this great info. I have one question though is it possible to create a variable file name for the csv so that we can do 5 units at a time sometimes. We bought 5 laptops the other day and could only do one then delete the file then the next and son on. It would have been perfect if i could have put usb drive into the machines one after the other.

    • Hi Dave,

      If you have 5 new laptops and you will manage them in the same Tenant you can use the script in this article. The script will append new lines in the CSV-file. If you want separate files I can give you an edited file

  3. Kumar Sadaram says:

    Hi Raymond, I am having an issue that some devices give me an error message as “Unable to retrieve device hardware data (has) from computer localhost”. Can you please advise what would be wrong with the device. I have re-imaged it as well.

    • Hi Kumar, in a command prompt can you please give me the output of winver?

      • Kris Lujanovic says:

        Get-CimInstance : A general error occurred that is not covered by a more specific error code.
        At C:\Program Files\WindowsPowerShell\Scripts\Get-WindowsAutoPilotInfo.ps1:211 char:17
        + … evDetail = (Get-CimInstance -CimSession $session -Namespace root/cimv …
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : NotSpecified: (:) [Get-CimInstance], CimException
        + FullyQualifiedErrorId : MI RESULT 1,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand

        C:\Program Files\WindowsPowerShell\Scripts\Get-WindowsAutoPilotInfo.ps1 : Unable to retrieve device hardware data
        (hash) from computer localhost
        At line:3 char:1
        + get-windowsautopilotinfo.ps1 -outputfile c:\deviceid.Csv
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : DeviceError: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-WindowsAutoPilotInfo.ps1

        • Kris Lujanovic says:

          so I ran the -debug
          2:45
          and entire script passed but
          2:45
          Confirm
          Are you sure you want to perform this action?
          Performing the operation “Set-ExecutionPolicy” on target “Unrestricted”.
          [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”): a
          C:\Program Files\WindowsPowerShell\Scripts\Get-WindowsAutoPilotInfo.ps1 : Missing an argument for parameter
          ‘OutputFile’. Specify a parameter of type ‘System.String’ and try again.
          At line:3 char:30
          + get-windowsautopilotinfo.ps1 -outputfile -Debug c:\deviceid.Csv
          + ~~~~~~~~~~~
          + CategoryInfo : InvalidArgument: (:) [Get-WindowsAutoPilotInfo.ps1], ParameterBindingException
          + FullyQualifiedErrorId : MissingArgument,Get-WindowsAutoPilotInfo.ps1

Leave a Reply

Your email address will not be published.