MSEndpointMgr

How to rename Windows 10 devices in Intune using PowerShell

With more and more organisations around embracing management through Endpoint Manager/Intune and using provisioning technologies like Autopilot, sometimes small things like the computer naming conventions can be overlooked. Autopilot has methods to use to apply computer naming, but what happens if you were to deploy several hundred or thousands of devices and need to change their computers names?

Well you could of course use the UI for this, however, this would be a somewhat tiresome and monotonous prospect depending on the quantity of machines to update. The other issue of course with this method is that human nature kicks in and the chance for a slip of the keyboard comes into play.

For clarity, at the time of writing what we are going to cover is only supported by Azure AD joined devices, and there are some considerations you will need to factor in maximum computer name lengths and naming restrictions outlined in the docs here – https://docs.microsoft.com/en-us/intune/remote-actions/device-rename

Microsoft Graph

In case you didn’t know, the underlying methods in which Microsoft online services communicate today are through something known as Graph. When you use the UI for instance in Endpoint Manager, underlying methods are used to take the information you are changing and upload this to the Graph API where the end action is initiated. With this in mind you can see how you could take the process of renaming and automate this, to provide a bulk on time action.

So the first thing we need to do is install the required PowerShell module and connect to the Graph API. This is achieved by running the following commands in your PowerShell window;

# Checking for Graph API
if ((Get-Module Microsoft.Graph.Intune) -eq $null) {
  # Install Graph API PowerShell cmdlets
  Install-Module -Name Microsoft.Graph.Intune
}
# Connect to Graph API
Connect-MSGraph

Running the command should result in a dialogue box similar to the one below appearing;

At this point we can now perform actions with other modules which use the graph API. For the purpose of this post we are going to talk about Autopilot devices using the Microsoft.Graph.Intune module. The module can be installed on your machine by running the following command from an adminisrative PowerShell prompt;

Install-Module -Name Microsoft.Graph.Intune

Once installed we can very quickly pull back information on devices within our tenant by running the following command;

Get-IntuneManagedDevice

Leveraging Graph – Bulk Renaming

Now that we have the required modules installed we can set about renaming devices through JSON posts through to Graph.

The first thing we need to do is obtain a list of devices that we wish to rename. In this example we are going to focus on those machines which used the standard naming convention that Autopilot uses today, this being Desktop- and Laptop-;

$Desktops = Get-IntuneManagedDevice | Where-Object {$_.DeviceName -match “Desktop-“
$Laptops = Get-IntuneManagedDevice | Where-Object {$_.DeviceName -match “Laptop-“

It is worth noting though that if you have had devices in Azure AD since before Autopilot was updated to name laptops accordingly, then those devices will also take the “Desktop-” format. In this instance we would be better to use a filter to narrow down the devices we wish to rename.

For example, the in the below command line we are returning all HP ZBook, ProBook and EliteBook devices;

With the list of devices now obtained, we can look at how we would like to rename our devices. In this instance I am going to use the following naming convention;

Desktops = DT-{{rand:6}}
Laptops = LT-{{rand:6}}

Here devices will be renamed with a shorter prefix of DT for Desktops and LT for Laptops, then we will have 6 random characters after a hyphen seperator.

Using Dynamic Variables

Alternatively you could use another piece of information from the device in your naming convention. For example the device serial either by using the “serial” built in value or by obtaining the serial and shortening it to a defined number of character;

Serial Number (First 8 characters and removing hyphens);
Where serial number = “3638-7607-8552-9649-8602-3245-85”
$newDeviceName = “DT” + ($Desktops | Select-Object -First 1 ).serialNumber.Substring(0,10).Replace(“-“,””)
Result = “DT-36387607”

If you wanted your device to be named in association with the user, you could query each device and looking at the “emailAddress”, “userPrincipalName” or the “userDisplayName” properties.

User
Where userDisplayName property = “John Smith”
$NewDeviceName = “DT” + ($Desktops | Select-Object -First 1 ).userDisplayName.Replace(” “,””)
Result = “DT-JohnSmyth”

Posting To Graph

Putting this together to form a script, we need to specify the Graph URL we are going to post information to. Here we are going to use the Beta API as it has the functionality we require. As we update each device in the script we will need to use the following;

$DeviceID = $Device.ID
$Resource = “deviceManagement/managedDevices(‘$DeviceID’)/setDeviceName”
$GraphApiVersion = “Beta”
$URI = “https://graph.microsoft.com/$graphApiVersion/$($resource)”

At this point we have the URL we need to post to, alone with the device ID that we would like to update. The next step is to create a JSON value that we can post with the required changes for that device.

Here we are focusing on the “deviceName” property, which you would be able to see from running the Get-IntuneManagedDevice command we ran earlier.

JSON Formatted Values

To automate the process of posting the updated device name we are going to use a foreach loop, after initially checking that the variable used contains at least one or more items. We the construct our JSON value, we can look at how JSON lists are formatted in this example by using the ConvertTo-JSON command for the first match in our desktops list;

$Desktops | Select-Object -First 1 | ConvertTo-Json

By narrowing down just the value we require, we end up by setting a variable with something similar to the below;

$JSONPayload = @"
{
deviceName:"$NewDeviceName"
}
"@
Putting This Together

With the list of devices obtained and the new naming structure, all we need to do is create a loop that performs the following command in order to update our devices;

Invoke-MSGraphRequest -HttpMethod POST -Url $uri -Content $JSONPayload

You can of course test this for yourself with a single device in order to ensure that the values are expected, but putting this together we end up with a script that we can run at anytime to correct this issue. In the below example I have added a logging function that also informs you of the changes being undertaken;

<#	
  .NOTES
  ===========================================================================
   Created on:   	04/02/2020 17:17
   Created by:   	MauriceDaly
   Organization: 	CloudWay
   Filename:     	Invoke-IntuneDeviceRename.ps1
  ===========================================================================
  .DESCRIPTION
    This script uses the Graph API to bulk rename Windows devices. It can for 
    example be used in a scenario where autopilot default naming has been used
    and a new standardised naming convention has been agreed upon.


  .EXAMPLE
    Invoke-IntuneDeviceRename.ps1 -MachineType "Desktop" 

#>
param
(
[parameter(Mandatory = $true)]
[ValidateSet('Desktop', 'Laptop')]   [string]$MachineType ) # Functions defined here function Write-LogEntry {   param (   
[parameter(Mandatory = $true, HelpMessage = "Value added to the log file.")]
[ValidateNotNullOrEmpty()]     
[string]$Value, 
[parameter(Mandatory = $true, HelpMessage = "Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.")]
[ValidateNotNullOrEmpty()] 
[ValidateSet("1", "2", "3")][string]$Severity,     
[parameter(Mandatory = $false, HelpMessage = "Name of the log file that the entry will written to.")]
    [ValidateNotNullOrEmpty()]
    [string]$FileName = "Invoke-IntuneDeviceRenaming.log"
  )
  # Determine log file location
  $LogFilePath = Join-Path -Path $env:TEMP -ChildPath $FileName
  
  # Construct time stamp for log entry
  $Time = -join @((Get-Date -Format "HH:mm:ss.fff"), " ", (Get-WmiObject -Class Win32_TimeZone | Select-Object -ExpandProperty Bias))
  
  # Construct date for log entry
  $Date = (Get-Date -Format "MM-dd-yyyy")
  
  # Construct context for log entry
  $Context = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
  
  # Construct final log entry
  $LogText = "&lt;![LOG[$($Value)]LOG]!&gt;&lt;time=""$($Time)"" date=""$($Date)"" component=""Intune-Device-Renaming"" context=""$($Context)"" type=""$($Severity)"" thread=""$($PID)"" file=""""&gt;"
  
  # Add value to log file
  try {
    Out-File -InputObject $LogText -Append -NoClobber -Encoding Default -FilePath $LogFilePath -ErrorAction Stop
    if ($Severity -eq 1) {
      Write-Verbose -Message $Value
    } elseif ($Severity -eq 3) {
      Write-Warning -Message $Value
    }
  } catch [System.Exception] {
    Write-Warning -Message "Unable to append log entry to Invoke-IntuneDeviceRenaming.log file. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)"
  }
}

TRY {
  
  # Checking for Graph API
  if ((Get-Module Microsoft.Graph.Intune) -eq $null) {
    # Install Graph API PowerShell cmdlets
    Write-LogEntry -Value "Installing Microsoft Graph Intune PowerShell module" -Severity 1
    Install-Module -Name Microsoft.Graph.Intune
  }
  
  # Connect to Graph API
  Write-LogEntry -Value "Connecting to Graph API" -Severity 1
  $GraphConnection = Connect-MSGraph
  
  if (-not ([string]::IsNullOrEmpty($GraphConnection.TenantID))) {
    # Set computer naming convention
    switch ($MachineType) {
      "Desktop" {
        $NewDeviceName = "DT-{{rand:6}}"
      }
      "Laptop" {
        $NewDeviceName = "LT-{{rand:6}}"
      }
    }
    
    # Get list of devices to rename from Graph
    Write-LogEntry -Value "Obtaining list of devices to rename" -Severity 1
    $DevicesToRename = Get-IntuneManagedDevice -filter "(Contains(deviceName, '$MachineType'))"
    Write-LogEntry -Value "Found $($DevicesToRename.Count) devices beginning with $MachineType" -Severity 1
    
    if ($DevicesToRename.Count -gt 0) {
      # Loop through devices
      Foreach ($Device in $DevicesToRename) {
        # Set graph URI to post data to
        $DeviceID = $Device.ID
        $Resource = "deviceManagement/managedDevices('$DeviceID')/setDeviceName"
        $GraphApiVersion = "Beta"
        $URI = "https://graph.microsoft.com/$graphApiVersion/$($resource)"
        
        Write-LogEntry -Value "Applying new naming convention logic" -Severity 1
        
          $JSONPayload = @"
{
deviceName:"$NewDeviceName"
}
"@
        
        # Post updated computer name via Graph API	
        if (-not ([string]::IsNullOrEmpty($NewDeviceName))) {
          Write-LogEntry -Value "Updating machine name $($Device.DeviceName) with device ID $DeviceID" -Severity 1
          Write-LogEntry -Value "Device primary user listed as $($Device.userDisplayName)" -Severity 1
          Write-LogEntry -Value "New computer name will use the format $NewDeviceName" -Severity 1
          Write-LogEntry -Value "Posting data to $URI" -Severity 1
          
          Invoke-MSGraphRequest -HttpMethod POST -Url $uri -Content $JSONPayload -Verbose -ErrorAction Continue
        } else {
          Write-Warning "Device $($Device.DeviceName) did not meeting matching criteria"
          Write-LogEntry -Value "Device $($Device.DeviceName) did not meeting matching criteria" -Severity 2
        }
        
        # Clear payload information
        $URI = $null
        $JSONPayload = $null
      }
    }
  }else {
    Write-LogEntry -Value "Unable to connect to MS Graph service. Aborting." -Severity 3
  }
} catch [System.Exception] {
  Write-LogEntry -Value "$($_.Exception.Message)" -Severity 3
  Write-Warning -Message $_.Exception.Message
}

Script log;

Verifying The Name Change

Once the script has been run, going into the Intune management portal  and selecting any of the matched devices should result in a visual confirmation that the device will be renamed upon its next restart;

We can also see this on the device itself;

Summary

So here we can see that with a little bit of automation, we can bulk rename devices in your tenant and ensure that you keep your naming convention across your Windows devices. I will be posting an extended PowerShell sample of the code included in this post over the next week for those who wish to have serial options to work with.

Thanks for reading.

Maurice Daly

Maurice has been working in the IT industry for the past 20 years and currently working in the role of Senior Cloud Architect with CloudWay. With a focus on OS deployment through SCCM/MDT, group policies, active directory, virtualisation and office 365, Maurice has been a Windows Server MCSE since 2008 and was awarded Enterprise Mobility MVP in March 2017. Most recently his focus has been on automation of deployment tasks, creating and sharing PowerShell scripts and other content to help others streamline their deployment processes.

Add comment

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.