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

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"}}

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:

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.

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.


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"}

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"}

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)

            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.

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