tabs-not-spaces / powers-hell-blog

new home for powers-hell.com blog
The Unlicense
4 stars 0 forks source link

Dynamically set the time zone of a device in Intune using Azure Maps & PowerShell | Powers Hell #17

Closed utterances-bot closed 2 years ago

utterances-bot commented 2 years ago

Dynamically set the time zone of a device in Intune using Azure Maps & PowerShell | Powers Hell

Let me start off by saying I wish I didn’t have to write this post. Setting the correct time zone of a Windows device shouldn’t be this difficult, especially with all of the management possibilities provided to us with Intune and the entire endpoint management stack. But here we are!

https://powers-hell.com/2020/08/31/setting-the-time-zone-of-an-intune-managed-device-using-azure-maps-powershell/

dridley23 commented 2 years ago

How do you get around challenges of finding Tz for devices built OnPrem?

tabs-not-spaces commented 2 years ago

I don't. This is a "best efforts" approach. Hopefully a device connected to an onPrem network would still get an external IP that was delegated somewhat close to their actual location.

mjr4077au commented 2 years ago

With newer PowerShell versions based on .NET 6, you can do a native lookup of the IANA time zone ID without having your own lookup table which is pretty neat.

Can't post a picture here, but calling [System.TimeZoneInfo]::FindSystemTimeZoneById('Australia/Sydney') in PowerShell 7.2.x will give you the goods.

tabs-not-spaces commented 2 years ago

Awesome find @mjr4077au I'll definitely check that out

mjr4077au commented 2 years ago

I received a lot of external help for this, but some managed code you can add to PowerShell 5.1 to use icu.dll to convert out an IANA time zone to Windows.

This was heavily inspired by Raymond Chen's sample C code from here as a proof of concept: https://devblogs.microsoft.com/oldnewthing/20210527-00/?p=105255

This could work really nicely in combination with your excellent suggestion of ipinfo.io via a proactive remediation script, something that I'll possibly play around with tomorrow.

$cp = [System.CodeDom.Compiler.CompilerParameters]::new()
$cp.CompilerOptions = '/unsafe'

Add-Type -CompilerParameters $cp -Namespace ICU -Name TimeZoneConverter -MemberDefinition '
    [DllImport("icu", ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static unsafe extern int ucal_getWindowsTimeZoneID(ushort* id, int len, ushort* winid, int winidCapacity, int* status);

    [DllImport("icu", ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static unsafe extern int ucal_getTimeZoneIDForWindowsID(ushort* winid, int len, IntPtr region, ushort* id, int idCapacity, int* status);

    private const int bufsize = 256;

    public static unsafe string IANAtoWindows(string id)
    {
        fixed (char* pId = id)
        {
            int status = 0;
            var buffer = stackalloc ushort[bufsize];
            var length = ucal_getWindowsTimeZoneID((ushort*)pId, id.Length, buffer, bufsize, &status);
            var outstr = Marshal.PtrToStringUni((IntPtr)buffer, length);
            return !String.IsNullOrWhiteSpace(outstr) ? outstr : null;
        }
    }

    public static unsafe string WindowsToIANA(string winid, string region)
    {
        fixed (char* pWinId = winid)
        {
            int status = 0;
            var buffer = stackalloc ushort[bufsize];
            var regptr = Marshal.StringToHGlobalAnsi(region);
            var length = ucal_getTimeZoneIDForWindowsID((ushort*)pWinId, winid.Length, regptr, buffer, bufsize, &status);
            var outstr = Marshal.PtrToStringUni((IntPtr)buffer, length);
            Marshal.FreeHGlobal(regptr);
            return !String.IsNullOrWhiteSpace(outstr) ? outstr : null;
        }
    }
'
PS C:\Users\username> [ICU.TimeZoneConverter]::IANAtoWindows('Australia/Sydney')
AUS Eastern Standard Time
PS C:\Users\username> [ICU.TimeZoneConverter]::WindowsToIANA('AUS Eastern Standard Time','AU')
Australia/Sydney
hahman14 commented 2 months ago

I was hoping that this would be the remedy to my time zone issues. Alas, I've discovered that even the GPS module is reporting the wrong information and that's likely what's throwing off the time zone in the first place. Unfortunately do to us using a web filter/proxy, the IP method wouldn't work either.

ngjrjeff commented 2 months ago

i'm trying to do to set country but have trouble convert from country to geoid. could you help me please?