Mr. Shiba What Time is it? – Get time remotely.

If you’ve ever worked in a large distributed environment you’ve likely experienced time issues. Maybe it’s not even so much an issue as you just want to know where the heck in the world a machine is. Especially in the current state of the world where almost every other day I wake up and go “WHAT YEAR IS IT” every day is Monday and everything is always on fire.

livememe.com - What Year Is It? (Jumanji)

I’m sure you’re thinking can’t I just invoke command to it? Or maybe just enter PSSession?

Well that’s what I thought too but in testing I got a mixed bag of results.

Enter-PSSession Get-Date

For the purpose of this I have a test server: “PROBRESFS01” and my local machine “WARMACHINE”. One is in eastern time, and the other is in Pacific time. A slight difference.

Eastern TimeZone
Pacific time zone

Now, one would assume that from here, I can run Get-Date and get the current time for PROBRESFS01. One would also be CORRECT in that assumption. This is because the sessions LOCALE information is sent across the session.

However, that’s not really convenient if you need to get the time for a group of servers, say something like all distribution points in an environment.

Just use Invoke-Command then right?

Well, kinda. Watch what happens when we use invoke command to get the current time.

Huh, for some reason it’s now showing the time retrieved from the remote server in MY time. As best as I can tell, this is because PowerShell is trying to help you by converting the time back into something you can understand. When it does this it does it for your current timezone.

OK but then how?

We can tackles this a couple of ways. The first option is just get the time zone information of the remote computer, and then convert your local machines time to it. However, that means if there is a difference in minutes between the two you won’t know about it. So what if we get both, and then convert it using .NET?

$ComputerName = "REMOTEPC"    
$TimeZone = Invoke-Command -ComputerName $ComputerName -ScriptBlock {Get-TimeZone}
$Time = Invoke-Command -ComputerName $ComputerName -ScriptBlock {Get-Date}
$CurrentTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(($Time), "$($TimeZone.ID)")
$CurrentTime

Well that’s a pretty good start. We can do better, what if we turn it into a function instead.

function Get-RemoteTime {
    [CmdletBinding()]
    param(
        [Parameter(HelpMessage = "The name of the remote computer")]
        [string]$ComputerName
    )
    #Get the timezone of the remote computer
    $TimeZone = Invoke-Command -ComputerName $ComputerName -ScriptBlock {Get-TimeZone}
    #Get the Time of the remote computer
    $Time = Invoke-Command -ComputerName $ComputerName -ScriptBlock {Get-Date}
    $CurrentTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(($Time), "$($TimeZone.ID)")
    return "The current time of the remote machine is: $($CurrentTime) it's TimeZone ID is: $($TimeZone.ID)"
}
Get-RemoteTime -ComputerName "RemotePCName"

Can we take it even further beyond? Of course we can lets get the time for all DPS: note if you have a CMG it will error on that one… Remote PowerShell to a cloud DP just sounds bad.

function Get-DPCurrentTime{
    [CmdletBinding()]
    param(
    [Parameter(HelpMessage = "Enter the name of the ConfigMgr Server",Mandatory = $true)]
    [string]$ConfigMgrServer,
    [Parameter(HelpMessage = "Enter the ConfigMgr Site Server", Mandatory = $true)]
    [string]$SiteCode
    )
    begin{}
    process{
        $DPList = Get-WmiObject -ComputerName $ConfigMgrServer -Namespace root\sms\site_$SiteCode -Query "select distinct ServerName from sms_distributionpointInfo"
        $List = [System.Collections.Generic.List[object]]::new()
        ForEach($Server in $DPList){
            $TimeZone = Invoke-Command -ComputerName $Server.ServerName -ScriptBlock {Get-TimeZone}
            $CurrentTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), "$($TimeZone.ID)")
            $Hash = [ordered]@{
                ServerName = $Server.SERVERNAME
                CurrentTime = $Currenttime
                TimeZone = $TimeZone.DisplayName
            }
            $Item = New-Object -TypeName PSobject -Property $Hash
            $List.Add($Item)
        }
    return $List
    }
}

Here you can grab the code from GitHub too:

https://github.com/JordanTheITGuy/PowerShell/blob/master/BlogPosts/HowTo%20-%20Get%20Local%20Time%20for%20All%20DPS/Get-LocalTimeDPS.ps1

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: