Check time on all PC's in a OU against Time Server

This topic contains 6 replies, has 4 voices, and was last updated by Profile photo of Eric Kettwig Eric Kettwig 2 months, 2 weeks ago.

  • Author
    Posts
  • #54349
    Profile photo of Eric Kettwig
    Eric Kettwig
    Participant

    So I need to check the time on all of the PCs that live in an OU and report on how many seconds their clock is off from the Time server. It seemed like it would be a pretty easy task at first, but my lack of experience with loops and if statements is showing here. I am on the third or fourth pass on this and I may just be going about it wrong. In this example the only thing written to my file is the "Time is Synced" or "Time is NOT Synced" message, the variable is out of scope (I believe) so I do not get the PC name and I only get the message for the last machine processed by the loop rather than all of them. I assume this is means the -Process block of the ForEach-Object loop is the only part that is processed for each entity and causing my script n the -End block to only run once for the last result from the -Process block, but it could just mean it is overwriting instead of appending?

    Anyways any guidance on how to fix this or of a better way to accomplish my task is appreciated.

     
    $CPc = $CPc = (Get-ADComputer -Filter * -SearchBase "OU=Test,OU=Workstations,OU=The,OU=IN,OU=SomeOU,DC=DOMAN,DC=com" -SearchScope Subtree).name
    $cpc | ForEach-Object -Process {Invoke-Command $_ {get-date} | New-TimeSpan -End (get-date) -OutVariable td}`
    -End {
                if (($td).seconds -le 60) {Add-Content C:\PSWorking\Tsync\InSync\Insync.txt "$_ Time is Synced"}
        else {Add-Content C:\PSWorking\Tsync\OutOfSync\OOSync.txt "$_ Time is NOT Synced"}}
    
  • #54350
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    The first question is how are you managing time in the environment today? Most Windows environments use the Windows Time Service to keep time synchronized. Here is a script similar to what you are attempting to do: https://gallery.technet.microsoft.com/scriptcenter/Check-timesource-W32TM-of-3d80b441

    The w32tm command also has commands to force or perform a sychronization. If this is setup properly, you shouldn't need to really mess with it.

    • #54355
      Profile photo of Eric Kettwig
      Eric Kettwig
      Participant

      Thanks for the reply, I already know where the machines are syncing from and have the ability to force them to sync. Unfortunately what I have been asked to provide is a listing of all the machines and how many seconds they have drifted from the PDC rather than to fix them. More than that though I am very curious to learn what I have done wrong in my script and how to fix it as working with loops and if statements is something I would like to be better at.

  • #54372
    Profile photo of
    Anonymous

    Hi,

    Not sure, but i think you need a last loop in your statement. like this:

    $computers | ForEach-Object -Process {Invoke-Command $_ {get-date} | New-TimeSpan -End (get-date) -OutVariable td}`
    -End { 
    
    $computers | ForEach-Object -Process {
    if (($td).seconds -le 60) {Add-Content C:\Temp\Insync.txt "$_ Time is Synced"}
        else {Add-Content C:\Temp\OSync.txt "$_ Time is NOT Synced"}
        }
        }
  • #54374
    Profile photo of
    Anonymous

    Sorry, posted wrong code above.

    $computers | ForEach-Object -Process {Invoke-Command $_ -scriptblock {get-date} | New-TimeSpan -End (get-date) -OutVariable td}` -End { 
    
    $computers | ForEach-Object -Process {
    
    if (($td).seconds -le 60) {Add-Content C:\PSWorking\Tsync\InSync\Insync.txt "$_ Time is Synced"}
        else {Add-Content C:\PSWorking\Tsync\InSync\OSync.txt "$_ Time is NOT Synced"}
        }
    }
  • #54375
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    Below is my take:

    $SearchBase = 'OU=Test,OU=Workstations,OU=The,OU=IN,OU=SomeOU,DC=DOMAN,DC=com'
    $Computers = (Get-ADComputer -Filter * -SearchBase $SearchBase -SearchScope Subtree)
    
    $Results = @(
    Invoke-Command -ComputerName @( $Computers.DNSHostName ) -ScriptBlock { Get-Date } | 
        ForEach-Object { 
            $td = New-TimeSpan -Start $_ -End (Get-Date)
    
            [PSCustomObject]@{
                ComputerName = $_.PSComputerName
                Status =
                    if ($td.seconds -le 60) {
                        'Time is Synced'
                    } else {
                        'Time is NOT Synced'
                    }
            }    
        }
    )
    
    $Results | Export-Csv -Path 'C:\PSWorking\Tsync\Status.csv' -NoTypeInformation
    

    Above should run faster because Invoke-Command will by default open up to 32 concurrent connections to remote computers to run the script provided. Invoke-Command will pipe the result of each Get-Date asynchronuously to ForEach-Object. ForEach-Object will calculate the time difference and emit a custom object with the computer name and time difference status. All custom objects emitted will be captured in the $results array which can easily be exported to CSV and filtered in Excel for the offenders.

    I hope that helps. Otherwise please do not hesistate to ask further questions for clarification or help on this thread.

    • #54401
      Profile photo of Eric Kettwig
      Eric Kettwig
      Participant

      Thank you all for the help. Daniel that works perfectly and it makes sense to boot, thank you.

You must be logged in to reply to this topic.