MSEndpointMgr

Automatically set Time Zone for devices provisioned using Windows Autopilot

When provisioning devices using Windows Autopilot and managing them with Microsoft Intune, there’s a ton of configuration options available using a range of different profiles, except for setting the time zone configuration. This still has to be accomplished using a Custom (OMA-URI) configuration profile and configure the following OMA-URI:

./Device/Vendor/MSFT/Policy/Config/TimeLanguageSettings/ConfigureTimeZone

A fellow Microsoft MVP, Peter van der Woude, has already covered the topic of setting the time zone using this custom configuration profile, so we won’t go deeper into this method. The issue with this method though, is that it’s not really a dynamic solution that’s easy to configure for a multi-national organization that are provisioning devices around the globe with Autopilot.

What we’re going to cover in this blog post, is a method that I’ve developed while working for a customer where the goal was to only utilize services available from a single trusted vendor such as Microsoft, since relying on 3rd-party public services was deemed unreliable for this particular customer. The dynamic method consists of combining the following services:

  • Location Services in Windows 10
  • Azure Maps REST API’s

By retrieving the current positioning data from the built-in location services capability of Windows 10, you’re able to call Azure Maps and essentially determine the correct time zone for the device that’s being provisioned. Using these two features and services, I’ve written a PowerShell script that performs a set of tasks with the sole purpose of setting the correct time zone configuration on a Windows 10 device that’s provisioned using Windows Autopilot.

Let’s walk through the required setup for accomplishing this.

Windows 10 built-in location services

Many of your have probably noticed this feature, or even decided not to allow it to be enabled in your organizations for various reasons. If you want to dig more into the feature, documentation from Microsoft is available below:

https://support.microsoft.com/en-us/help/4468240/windows-10-location-service-and-privacy

One obstacle that I had to deal with to automatically set the time zone based on current positioning data, was that the location services on more recent Windows 10 builds is by default turned off. So, in order to have it turned on, I had to develop a small function of PowerShell code that enables locations services.

I’d like to point out though that the method used in the code shown below, has been tested and verified on Windows 10 version 1909 and 2004, however I’d not trust that it’s a method that could be expected to work in upcoming versions of Windows 10, in case Microsoft changes the way the feature works. Currently, there’s no PowerShell cmdlet or other method to enable locations services other than touching on some registry values.

In regards to this, I’ll attempt to test and verify the function to support upcoming Windows 10 version, as they become available.
function Enable-LocationServices {
    $LocationConsentKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\location"
    Write-LogEntry -Value "Checking registry key presence: $($LocationConsentKey)" -Severity 1
    if (-not(Test-Path -Path $LocationConsentKey)) {
        Write-LogEntry -Value "Presence of '$($LocationConsentKey)' key was not detected, attempting to create it" -Severity 1
        New-Item -Path $LocationConsentKey -Force | Out-Null
    }
    
    $LocationConsentValue = Get-ItemPropertyValue -Path $LocationConsentKey -Name "Value"
    Write-LogEntry -Value "Checking registry value 'Value' configuration in key: $($LocationConsentKey)" -Severity 1
    if ($LocationConsentValue -notlike "Allow") {
        Write-LogEntry -Value "Registry value 'Value' configuration mismatch detected, setting value to: Allow" -Severity 1
        Set-ItemProperty -Path $LocationConsentKey -Name "Value" -Type "String" -Value "Allow" -Force
    }
    
    $SensorPermissionStateRegValue = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}"
    $SensorPermissionStateValue = Get-ItemPropertyValue -Path $SensorPermissionStateRegValue -Name "SensorPermissionState"
    Write-LogEntry -Value "Checking registry value 'SensorPermissionState' configuration in key: $($SensorPermissionStateRegValue)" -Severity 1
    if ($SensorPermissionStateValue -ne 1) {
        Write-LogEntry -Value "Registry value 'SensorPermissionState' configuration mismatch detected, setting value to: 1" -Severity 1
        Set-ItemProperty -Path $SensorPermissionStateRegValue -Name "SensorPermissionState" -Type "DWord" -Value 1 -Force
    }
    
    $LocationServiceStatusRegValue = "HKLM:\SYSTEM\CurrentControlSet\Services\lfsvc\Service\Configuration"
    $LocationServiceStatusValue = Get-ItemPropertyValue -Path $LocationServiceStatusRegValue -Name "Status"
    Write-LogEntry -Value "Checking registry value 'Status' configuration in key: $($LocationServiceStatusRegValue)" -Severity 1
    if ($LocationServiceStatusValue -ne 1) {
        Write-LogEntry -Value "Registry value 'Status' configuration mismatch detected, setting value to: 1" -Severity 1
        Set-ItemProperty -Path $LocationServiceStatusRegValue -Name "Status" -Type "DWord" -Value 1 -Force
    }

    $LocationService = Get-Service -Name "lfsvc"
    Write-LogEntry -Value "Checking location service 'lfsvc' for status: Running" -Severity 1
    if ($LocationService.Status -notlike "Running") {
        Write-LogEntry -Value "Location service is not running, attempting to start service" -Severity 1
        Start-Service -Name "lfsvc"
    }
}

Azure Maps REST API’s

As the main requirement for this solution was to only rely on a single service provider, in this case Microsoft, I steered my focus to Azure to look for any available cloud resources that would allow me to retrieve a time zone based on the current positioning data. Azure Maps provides various REST API’s and one in particular found my interest:

https://docs.microsoft.com/en-us/rest/api/maps/timezone/gettimezonebycoordinates

Azure Maps have an API named GetTimeZoneByCoordinates. From the looks of it I could pass my current positioning data translated into coordinates and receive the IANA time zone id as a response from the request. The best part, it also supported passing a shared key instead of dealing with authentication in terms tokens, which would not be ideal during the provisioning phase of a device. I decided to look more into this API and other API’s from Azure Maps and build the solution on that.

Worth knowing about Azure Maps, if you’re looking to use the time zone configuration method I’m talking about in this post, is that Azure Maps costs money, not much and is free up to a certain point in terms of calls against the API. See the official pricing list for more information.

https://azure.microsoft.com/en-us/pricing/details/azure-maps/

Download the PowerShell script

In our public GitHub repository, I’ve made the Set-WindowsTimeZone.ps1 script available for download:

https://github.com/MSEndpointMgr/Intune/blob/master/Autopilot/Set-WindowsTimeZone.ps1

Implementation instructions

To use the script mentioned above, you’ll need to first setup Azure Maps, which is pretty straight forward but also create a PowerShell script in Microsoft Intune that’s targeted for the devices being provisioning using Windows Autopilot. Follow the instructions in the sub-sections below to accomplish this.

Setup Azure Maps

From within the Azure portal (portal.azure.com), browse All services and search for Azure Maps. Select Azure Maps Accounts.

Click on Add.

Select any desired existing subscription where you want Azure Maps to be created under. If you desire to divide costs and have a separate subscription only for Azure Maps to track costs, go back and create it before you continue with this guide. Additionally, select an existing resource group or create a new one (permissions to create new resource groups or select existing requires you to have Contributor, or Owner permissions in the selected subscription). Name the Azure Maps account that you’re creating, accept the license and privacy statement and click Create.

Once the resources have successfully been deployed, go to the newly created Azure Maps account. In the left pane, go to Authentication.

Make a note of the Primary Key and copy it for later use. This shared key is essentially what we’ll be using as authentication when the Azure Maps API’s are called within the PowerShell script.

Create PowerShell script in Microsoft Intune

Download the Set-WindowsTimeZone.ps1 script from our GitHub repository. Edit the script on the following line to include the shared key copied from Azure Maps authentication in earlier steps:

Next, in the Microsoft Endpoint Manager admin console (endpoint.microsoft.com) under Device – Windows – PowerShell scripts create a new script. Provide a name of the script and click Next.

Browse to the modified Set-WindowsTimeZone.ps1 script that should at this point include the shared key and select the script file. Configure the script to run in a 64-bit PowerShell host, or else the script will attempt to check and set location services related key and values in the wrong place.

Complete the rest of the wizard and finally assign the script to your Windows Autopilot device groups used for provisioning.

Provisioning and user experience

When provisioning happens you can track the Set-WindowsTimeZone.ps1 script’s progress and verbose output in a log file placed in C:\Windows\Temp.

In this log, you’ll see that location services in Windows 10 is turned on, current positioning data is retrieved and passed on to Azure Maps REST API’s to determine the correct time zone.

After a successful provisioning of the device, the time zone has been set and can be viewed within the settings app.

Hopefully this will help in the journey onwards to a modern workplace.

Nickolaj Andersen

Chief Technical Architect and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences such as Microsoft Ignite, NIC Conference and IT/Dev Connections including nordic user groups.

Add comment

Sponsors

Categories

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