Skip to content

Instantly share code, notes, and snippets.

Created May 8, 2016 14:02
Show Gist options
  • Save anonymous/5e97eebc13bcc6357cb8e373cc3eb952 to your computer and use it in GitHub Desktop.
Save anonymous/5e97eebc13bcc6357cb8e373cc3eb952 to your computer and use it in GitHub Desktop.
Check Multiple NTP Clients in Powershell
$cred=get-credential
$Time_Server1='time.windows.com'
$Time_Server2='time.nist.gov'
$HostFileLocation='hostnames.txt'
############ Admin must change the parameters accordingly in the above section ###########
####### Trim the IP addresses check the port connections for 5985 and 5986 for WimRM Connection #######
#######################################################################################################
if (Test-Path $HostFileLocation)
{
$HostNamesTrimmed=(gc $hostFileLocation) | foreach { $_.trim() }
############### function to check the ports 5985 & 5986 are opened to allow WinRM Connection ##############
$HostNamesTrimmed | foreach {
$job1=start-job -name job1 -scriptBlock { param($Destination)
$Socket1= New-Object Net.Sockets.TcpClient
$IAsyncResult1= [IAsyncResult] $Socket1.BeginConnect($Destination,'5985', $null, $null)
$success1= $IAsyncResult1.AsyncWaitHandle.WaitOne(100,$true)
return $Socket1.Connected
$Socket1.close()
} -ArgumentList $_
$job2=start-job -name job2 -scriptBlock { param($Destination)
$Socket2= New-Object Net.Sockets.TcpClient
$IAsyncResult2= [IAsyncResult] $Socket2.BeginConnect($Destination,'5986', $null, $null)
$success2= $IAsyncResult2.AsyncWaitHandle.WaitOne(200,$true)
return $Socket2.Connected
$Socket2.close()
} -ArgumentList $_
$Socket1Connected=wait-job -name job1 | receive-job
$Socket2Connected=wait-job -name job2 | receive-job
remove-job -name job1
remove-job -name job2
if (($Socket1Connected) -OR ($Socket2Connected))
{
[array]$hostlist+=$_
}
else
{
Write-Host -Fore Red "$_`: Port 5985 or 5986 is not opened for WinRM Connection. Please make sure your system is up and Firewall is allowed"
}
}
}
####### If a valid host file not exist, then exit ;P ##############
else{
Write-Host -Fore Red "Host file with list of IP addresses is not found. Now exit...";exit;
}
############### Output the value of time servers to be set ####################################
"`n"
if ($Time_Server1)
{ Write-Host -Fore Cyan "The NTP1 value to be set is $Time_Server1" }
if ($Time_Server2)
{ Write-Host -Fore Cyan "The NTP2 value to be set is $Time_Server2" }
########################## Get the registry info & Time info from WMI call #####################
function get-regkey {
[CmdletBinding()]
param (
[parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string]$computername="$env:COMPUTERNAME"
)
PROCESS {
$rh = '2147483650' # the value for HKLM
$key = 'Software\Microsoft\Windows\CurrentVersion\DateTime\Servers'
$reg = [wmiclass]"\\$($computername)\root\default:StdRegprov"
$default=$reg.GetStringValue($rh, $key)
$server1=$reg.GetStringValue($rh, $key, '1')
$server2=$reg.GetStringValue($rh, $key, '2')
########### fetch from registry for the NTP parameters #########
if ( !$default.ReturnValue) { $def=$default.sValue } else { $def="The registry Key not Found for $key."}
if ( !$server1.ReturnValue) { $serv1=$server1.sValue } else { $serv1="Not Found"}
if ( !$server2.ReturnValue) { $serv2=$server2.sValue } else { $serv2="Not Found"}
############# fetch the time info from WMI ##################
$serviceStatus=(get-service w32time).status
$timeinfo=get-wmiobject -class win32_operatingsystem
$GMTOffsetInMinutes=[string]($timeinfo.CurrentTimeZone)
$currentTime=$timeinfo.ConvertToDateTime($timeinfo.LocalDateTime)
$ServerName=$timeinfo.CSName
$OSversion=$timeinfo.version
############# fetch the TimeZone info from WMI ###############
$TimezoneInfo=(Get-WmiObject -class win32_timezone).standardname
################### covert the Offset minute value to hour:minute string format ###########
if([math]::sign($timeinfo.CurrentTimeZone) -eq 1)
{
$t=new-TimeSpan -minutes ($timeinfo.CurrentTimeZone)
$GMTOffset='+'+[string]$t.hours+':'+[string]$t.minutes
}
elseif ([math]::sign($timeinfo.CurrentTimeZone) -eq "-1")
{
$t=new-TimeSpan -minutes ([math]::abs($timeinfo.CurrentTimeZone))
$GMTOffset='-'+[string]$t.hours+':'+[string]$t.minutes
}
return $ServerName,$def,$serv1,$serv2,$currentTime,$serviceStatus,$GMTOffset,$GMTOffsetInMinutes,$TimezoneInfo,$OSversion
}}
####################### Set the registry info to the values ############################
function set-regkey { param([string]$regValue1='',[string]$regValue2='',[string]$IPAddress,[string]$computername="$env:COMPUTERNAME")
$rh = '2147483650' # the value for HKLM
$key = 'Software\Microsoft\Windows\CurrentVersion\DateTime\Servers'
$reg = [wmiclass]"\\$($computername)\root\default:StdRegprov"
if ($regValue1)
{ $result1=$reg.SetStringValue($rh, $key, '1', $regValue1)
if (!$result1.returnValue)
{ Write-Host -fore green "$($IPAddress) has successfully changed the NTP1 Value to $regValue1" }
else
{Write-Host -Fore Red "$($IPAddress)`:Unknown Error Occurred. Please make sure you have write access to registry. Time Server value is not changed`n" }
}
if ($regValue2)
{ $result2=$reg.SetStringValue($rh, $key, '2', $regValue2)
if (!$result2.returnValue)
{ Write-Host -fore green "$($IPAddress) has successfully changed the NTP2 Value to $regValue2" }
else
{ Write-Host -Fore Red "$($IPAddress)`:Unknown Error Occurred. Please make sure you have write access to registry. Time Server value is not changed`n" }
}
}
########## Create the custom Psobject to store the output from invoked action ##########
$properties=@{'ServerName'="";'IPAddress'="";'DefSvr'="";'TimeServer1'="";'TimeServer2'="";'CurrentTime'="";'TimeService'="";'GMTOffset'="";'GMTOffsetInMinutes'="";'TimezoneInfo'="";'OSversion'=""}
$serverObj= New-Object -TypeName PsObject -Prop $properties
$ServiceStopped=0
$output=@()
$Timer= [Diagnostics.Stopwatch]::StartNew() ### New starting point of the timer object
for ($i=0;$i -lt $hostlist.count; $i++)
{
################ Get the Server info and time by calling functions #######################
$temp=Invoke-Command -Computername $hostlist[$i] -Credential $cred -ScriptBlock ${function:get-regkey}
$serverObj.ServerName=$temp[0]
$serverObj.DefSvr=$temp[1]
$serverObj.TimeServer1=$temp[2]
$serverObj.TimeServer2=$temp[3]
$serverObj.CurrentTime=$temp[4]
$serverObj.TimeService=$temp[5]
$serverObj.GMTOffset=$temp[6]
$serverObj.GMTOffsetInMinutes=$temp[7]
$serverObj.TimezoneInfo=$temp[8]
$serverObj.OSversion=$temp[9]
$serverObj.IPAddress=$hostlist[$i]
$output+= $serverObj | select ServerName,IPAddress,TimeService,TimeServer1,TimeServer2,DefSvr,GMTOffset,CurrentTime,GMTOffsetInMinutes,TimezoneInfo,OSversion
if ($serverObj.TimeService.Value -eq "Stopped") { $ServiceStopped=1}
}
$output | ft ServerName,IPAddress,TimeService,TimeServer1,TimeServer2,DefSvr,GMTOffset,TimezoneInfo,CurrentTime -auto
############################### Compare the given NTP1 values with the value in registry #############################
if ($Time_Server1)
{
$output | foreach {
if($_.TimeServer1 -ine $Time_Server1)
{
Write-Host -fore red "$($_.IPAddress) does not have a valid NTP Server"
[array]$InvalidTimeServer1IPs+=$_.IPAddress
}
}
############## Once user confirmed,Change the NTP1 value of each Servers by calling set-regkey function #################
if($InvalidTimeServer1IPs)
{
$ToCorrectNTPServer1=0
do
{
[console]::foregroundcolor="yellow"
$ToCorrectNTPServer1=Read-Host "Do You want to change First NTP Server value of these $($InvalidTimeServer1IPs.count) Server(s) to $($Time_Server1.Trim())?(y/n)"
[console]::foregroundcolor="white"
if ($ToCorrectNTPServer1 -eq 'y'){
for ($i=0;$i -lt $InvalidTimeServer1IPs.count;$i++)
{
Invoke-Command -Computername $InvalidTimeServer1IPs[$i] -Credential $cred -ScriptBlock ${function:set-regkey} -ArgumentList $Time_Server1,$Null,$InvalidTimeServer1IPs[$i]
}
$ToCorrectNTPServer1=1
}
elseif ($ToCorrectNTPServer1 -eq 'n' ){$ToCorrectNTPServer1=1}
else {$ToCorrectNTPServer1=0}
} while (!$ToCorrectNTPServer1)
}
}
############################### Compare the given NTP2 values with the value in registry ##################
if ($Time_Server2)
{
$output | foreach {
if($_.TimeServer2 -ine $Time_Server2)
{
Write-Host -fore red "$($_.IPAddress) does not have a valid NTP2 Server"
[array]$InvalidTimeServer2IPs+=$_.IPAddress
}
}
############## Once user confirmed,Change the NTP2 value of each Servers by calling set-regkey function #################
if($InvalidTimeServer2IPs)
{
$ToCorrectNTPServer2=0
do
{
[console]::foregroundcolor="yellow"
$ToCorrectNTPServer2=Read-Host "Do You want to change Second NTP Server value of these $($InvalidTimeServer2IPs.count) Server(s) to $($Time_Server2.Trim())?(y/n)"
[console]::foregroundcolor="white"
if ($ToCorrectNTPServer2 -eq 'y'){
for ($i=0;$i -lt $InvalidTimeServer2IPs.count;$i++)
{
Invoke-Command -Computername $InvalidTimeServer2IPs[$i] -Credential $cred -ScriptBlock ${function:set-regkey} -ArgumentList $Null,$Time_Server2,$InvalidTimeServer2IPs[$i]
}
$ToCorrectNTPServer2=1
}
elseif ($ToCorrectNTPServer2 -eq 'n' ){$ToCorrectNTPServer2=1}
else {$ToCorrectNTPServer2=0}
} while (!$ToCorrectNTPServer2)
}
}
if (!($InvalidTimeServer1IPs -AND $InvalidTimeServer2IPs))
{ Write-Host -Fore Green "The NTP settings are correct on All Servers"}
################### Find the Standard GMT Offset and output the incorrect TimeZone #############
if (($NumberOfTimeZones=$output | group-object -property TimezoneInfo | sort-object -property count -desc | select -first 1).count -eq 1)
{
echo "It have some problems in getting TimeZone information, so using your Time Zone as Default"
$GMTOffsetStandard= (Get-WmiObject -class win32_timezone).standardname
echo "The Standard Timezone becomes $GMTOffsetStandard"
}
else
{
Write-Host -fore Green "`nGetting Standard Timezone is OK"
$GMTOffsetStandard= ($output | group-object -property TimezoneInfo | sort-object -property count -desc | select -first 1).name
Write-Host "The Standard Time zone is $GMTOffsetStandard"
}
#################### Compare each computer's time zone with the standard time zone,by creating TimeZone objects ################
$IncorrectTimeZoneServers=@()
$IncorrectTimeZoneServerInfo=New-Object -TypeName PsObject -Property @{IP="";OSversion=""}
$output | foreach {
if ( $_.TimezoneInfo -eq $GMTOffsetStandard )
{}
else {
$IncorrectTimeZoneServerInfo.IP=$_.IPAddress
$IncorrectTimeZoneServerInfo.OSversion=$_.OSversion
Write-Host -fore red "$($_.IPAddress) has a wrong Time Zone"
$IncorrectTimeZoneServers+=$IncorrectTimeZoneServerInfo | select IP,OSversion
}
}
###### Prompt the user to change the TimeZone and if yes, take action according to OS version ###########
if ($IncorrectTimeZoneServers)
{
$ToCorrectTimeZone=0
do
{
[console]::foregroundcolor="yellow"
$ToCorrectTimeZone=Read-Host "Do you want to correct the incorrect Time Zones?(y/n)"
[console]::foregroundcolor="white"
if ($ToCorrectTimeZone -eq 'y'){
$IncorrectTimeZoneServers | foreach {
if ( $_.OSversion.split('.')[0] -lt 6)
{
Invoke-Command -ComputerName $_.IP -Credential $cred -ScriptBlock { param($IP,$NewTimeZone)echo "control.exe timedate.cpl,,/Z$NewTimeZone" | cmd.exe
if ((Get-WmiObject -class win32_timezone).StandardName -eq $NewTimeZone) {Write-Host -Fore Green "$IP`:Setting TimeZone is OK"}
} -ArgumentList $_.IP,$GMTOffsetStandard
}
else
{
Invoke-Command -ComputerName $_.IP -Credential $cred -ScriptBlock { param($IP,$NewTimeZone)tzutil.exe /s $NewTimeZone
if ((Get-WmiObject -class win32_timezone).StandardName -eq $NewTimeZone) {Write-Host -Fore Green "$IP`:Setting TimeZone is OK"}
} -ArgumentList $_.IP,$GMTOffsetStandard
}
}
$ToCorrectTimeZone=1
}
elseif ($ToCorrectTimeZone -eq 'n' ){$ToCorrectTimeZone=1}
else {$ToCorrectTimeZone=0}
} while (!$ToCorrectTimeZone)
}
else
{ Write-Host -fore Green "All servers have the correct TimeZone" }
############ Find the Standard Time by group-object method on the first two part of time, the 'sec' part is as another property##########################
############ Creating Array of Current Time values to find the standard Time ############
$ServerTimeArray=@()
$ServerTimeObject=New-Object -TypeName PsObject -Property @{IPAddress="";ComparePart="";LatestPart=""} ## ComparePart is MM/dd/YYYY hh:mm & LatestPart is ss to find avg
for($i=0;$i -lt $output.count;$i++) {
$TempIPAddress=[string]$output[$i].IPAddress
$TempStringFormat=[string]$output[$i].CurrentTime ### the value in CurrentTime is [DateTime] format, so we convert to string
$TempFirstPart=$TempStringFormat.split(':')[0]
$TempSecondPart=$TempStringFormat.split(':')[1]
$ServerTimeObject.IPAddress=$TempIPAddress
$ServerTimeObject.ComparePart=$TempFirstPart+':'+$TempSecondPart
$ServerTimeObject.LatestPart=$TempStringFormat.split(':')[2]
$ServerTimeArray+=$ServerTimeObject | select IPAddress,ComparePart,LatestPart
}
############ function to find the average sec(s) value of two duplicate server times in minutes ##############
function get-AvgSecond()
{
$count=($ServerTimeArray | Group-Object -Property ComparePart | sort-object -property count -desc | select -first 1).count
$ChosenServerTimeGroup= $ServerTimeArray | Group-Object -Property ComparePart | sort-object -property count -desc | select -first 1 -expandproperty group
$ChosenServerTimeGroup | foreach { [int]$LatestPartSum+=$_.LatestPart }
return $AvgLatestPart=[math]::round($LatestPartSum/$count)
}
############ Code to find the the standard time, If not OK, use the local time as standard time #############
if (($ServerTimeArray | Group-Object -Property ComparePart | sort-object -property count -desc | select -first 1).count -eq 1)
{
$StandardTime=Get-WMIObject -Class Win32_operatingsystem
$StandardTimeExact=$StandardTime.ConvertToDateTime($StandardTime.LocalDateTime)
Write-Host -Fore Red "`nCan't choose the Standard Time among servers !"
Write-Host -Fore Yellow "So now the Your machine Time $StandardTimeExact becomes the standard time"
}
else {
$StandardTime=($ServerTimeArray | Group-Object -Property ComparePart | sort-object -property count -desc | select -first 1).name
#Write-Host "`nThe Standard Time is $StandardTime" ### You can output this value, exact to minutes match
$AvgSecond=get-AvgSecond
$StandardTimeExact=[datetime]($StandardTime+':'+$AvgSecond) ### cannot validate standardtime among servers, so using average second value
Write-Host "`nThe Exact Standard Time is $StandardTimeExact"
}
########### Compare each computer's time with the standard time(hh:mm only) and prompts the user to change the current value #####
$i=0;
$IncorrectTimeServerIPs=@();
$ServerTimeArray | foreach {
if ( $_.ComparePart -eq $StandardTime )
{}
else { $IncorrectTimeServerIPs+=$_.IPAddress
Write-Host -fore Red "$($_.IPAddress) has a wrong Date/Time"
}
$i++;
}
########### Check each server has the correct time & prompt user to correct ###################
if(!$IncorrectTimeServerIPs.count)
{ Write-Host -fore Green "All servers have the Correct Time" }
else {
$ChangeServerTimeValue=0
do
{
[console]::foregroundcolor="yellow"
$ChangeServerTimeValue=Read-Host "Do you want to change the value of All time servers to Standard time?(y/n)"
[console]::foregroundcolor="white"
if ($ChangeServerTimeValue -eq 'y'){
$Timer.stop()
Write-Host "The base standard tims is $StandardTimeExact"
Write-Host "The elpsed time waiting your confirm is $($Timer.elapsed.seconds) sec"
$ApplyTime= $StandardTimeExact.addseconds($Timer.elapsed.seconds)
Write-Host "So the new standard time to be apply is $ApplyTime"
Invoke-Command -ComputerName $IncorrectTimeServerIPs -Credential $cred -ScriptBlock {param($NewDate) Set-Date $NewDate | out-null} -ArgumentList $ApplyTime
$ChangeServerTimeValue=1
}
elseif ($ChangeServerTimeValue -eq 'n' ){$ChangeServerTimeValue=1}
else {$ChangeServerTimeValue=0}
} while (!$ChangeServerTimeValue)
}
######## Check the stopped services & restart if admin confirms###################
if ( $ServiceStopped -eq 1)
{
$StoppedServers=$null;
#[console]::foregroundcolor="magenta"
$StoppedServers+=$output | where { $_.TimeService.Value -eq "Stopped" } | select ServerName,IPAddress,TimeService,TimeServer1,TimeServer2,DefSvr,CurrentTime
$StoppedServers | ft ServerName,IPAddress,TimeService -auto
#[console]::foregroundcolor="white"
$NumberOfStoppedServices=$output | where { $_.TimeService.Value -eq "Stopped" } | measure-object
Write-Host -Fore Red "$($NumberOfStoppedServices.count) Time Service(s) are stopped"
################ Start the Time Service If admin comfirms ####################
$StartServiceConfirm=0
[console]::foregroundcolor="yellow"
do
{
$StartServiceConfirm=Read-Host "Do you want to start the services?(y/n)"
if ($StartServiceConfirm -eq 'y'){
$StoppedServers | foreach {
Invoke-Command -COMPUTERNAME $($_.IPAddress) -Credential $cred -ScriptBlock { start-service -name w32time -EA SilentlyContinue}
if ((Invoke-Command -COMPUTERNAME $($_.IPAddress) -Credential $cred -ScriptBlock { Get-service -name w32time}).status -eq "Running")
{ Write-Host -Fore Green "Windows Time Service has successfully started on $($_.IPAddress)"}
else { Write-Host -Fore Red "Cannot start the service on $($_.IPAddress). Please make sure the Time Service is not currently disabled"}
}
$StartServiceConfirm=1 }
elseif ($StartServiceConfirm -eq 'n' ){$StartServiceConfirm=1}
else {$StartServiceConfirm=0;}
} while (!$StartServiceConfirm)
[console]::foregroundcolor="white"
}
####################### List the NTP Settings after correction #########################
Write-Host "`nThe NTP Status after correction..."
$output=@()
for ($i=0;$i -lt $hostlist.count; $i++)
{
################ Get the Server info and time by calling functions #######################
$temp=Invoke-Command -Computername $hostlist[$i] -Credential $cred -ScriptBlock ${function:get-regkey}
$serverObj.ServerName=$temp[0]
$serverObj.DefSvr=$temp[1]
$serverObj.TimeServer1=$temp[2]
$serverObj.TimeServer2=$temp[3]
$serverObj.CurrentTime=$temp[4]
$serverObj.TimeService=$temp[5]
$serverObj.GMTOffset=$temp[6]
$serverObj.GMTOffsetInMinutes=$temp[7]
$serverObj.TimezoneInfo=$temp[8]
$serverObj.OSversion=$temp[9]
$serverObj.IPAddress=$hostlist[$i]
$output+= $serverObj | select ServerName,IPAddress,TimeService,TimeServer1,TimeServer2,DefSvr,GMTOffset,CurrentTime,GMTOffsetInMinutes,TimezoneInfo,OSversion
if ($serverObj.TimeService.Value -eq "Stopped") { $ServiceStopped=1}
}
[console]::Foregroundcolor="Cyan"
$output | ft ServerName,IPAddress,TimeService,TimeServer1,TimeServer2,DefSvr,GMTOffset,TimezoneInfo,CurrentTime -auto
[console]::Foregroundcolor="White"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment