Microsoft Scripting Guy Ed Wilson here. I finally had a chance to sit down and catch my breath from the 2010 Scripting Games. I reviewed some awesome scripts, and learned many new tricks. I happened to notice that my desktop computer clock was about five minutes slow. I checked and the domain controller was also slow. After looking around, I realized I had never set an external time source for my domain controller—something that was kind of easy to miss because it is running Windows Server 2008 R2 Core Edition.
After doing a bit of research, I ran across an excellent knowledge base article that talks about configuring an authoritative time server in Windows Server. The article KB816042 contains a number of registry entries. Hmm, I thought, an opportunity to write a Windows PowerShell script.
The complete ConfigureInternetTimeSource.ps1 script is seen here.
ConfigureInternetTimeSource.ps1
Param($computer = “Hyperv”, $user = “nwtraders\administrator”)
$psSession = New-PSSession -ComputerName $computer -Credential $user
Invoke-Command -Session $PSSession -ScriptBlock {
$timeRoot = “HKLM:\SYSTEM\CurrentControlSet\services\W32Time”
$ntpServer = “time.windows.com,0x1 nist1-ny.ustiming.org,0x1”
Set-ItemProperty -path “$timeroot\parameters” -name type -Value “NTP”
Set-ItemProperty -path “$timeroot\parameters” -name NtpServer -Value $ntpServer
Set-ItemProperty -path “$timeroot\config” -name AnnounceFlags -Value 5
Set-ItemProperty -path “$timeroot\config” -name MaxPosPhaseCorrection -Value 1800
Set-ItemProperty -path “$timeroot\config” -name MaxNegPhaseCorrection -Value 1800
Set-ItemProperty -path “$timeroot\TimeProviders\NtpServer” -name Enabled -Value 1
Set-ItemProperty -path “$timeroot\TimeProviders\NtpClient” -name SpecialPollInterval -Value 900
Register-WmiEvent -Query `
“select * from __InstanceModificationEvent within 5 where targetinstance isa ‘win32_service'” `
-SourceIdentifier stopped
Stop-Service -Name w32Time
Wait-Event -SourceIdentifier stopped
Start-Service -Name w32Time
Unregister-Event -SourceIdentifier stopped
Remove-Event -SourceIdentifier stopped
} # end invoke-command
Remove-PSSession -Session $psSession
Because I want to run this script against a remote computer, I create a Windows PowerShell remote session:
$psSession = New-PSSession -ComputerName $computer -Credential $user
After the session has been created, I use it to set the registry keys. But because I want all of my commands to be executed at the same time, I use a single Invoke-Command ScriptBlock. The command therefore begins as seen here:
Invoke-Command -Session $PSSession -ScriptBlock {
Everything else is basically between the curly brackets for the ScriptBlock. The commands to modify the registry are seen here:
$timeRoot = “HKLM:\SYSTEM\CurrentControlSet\services\W32Time”
$ntpServer = “time.windows.com,0x1 nist1-ny.ustiming.org,0x1”
Set-ItemProperty -path “$timeroot\parameters” -name type -Value “NTP”
Set-ItemProperty -path “$timeroot\parameters” -name NtpServer -Value $ntpServer
Set-ItemProperty -path “$timeroot\config” -name AnnounceFlags -Value 5
Set-ItemProperty -path “$timeroot\config” -name MaxPosPhaseCorrection -Value 1800
Set-ItemProperty -path “$timeroot\config” -name MaxNegPhaseCorrection -Value 1800
Set-ItemProperty -path “$timeroot\TimeProviders\NtpServer” -name Enabled -Value 1
Set-ItemProperty -path “$timeroot\TimeProviders\NtpClient” -name SpecialPollInterval -Value 900
After the registry entries have been made, it is time to stop and to start the w32time service. Before stopping the w32time service, I create a temporary WMI event consumer by using the Register-WmiEvent cmdlet. This will monitor the status of services on the computer. When an __InstanceModificationEvent occurs (such as stopping or starting a service), an event is triggered. The code to do this is seen here:
Register-WmiEvent -Query `
“select * from __InstanceModificationEvent within 5 where targetinstance isa ‘win32_service'” `
-SourceIdentifier stopped
Now I stop the w32time service, and wait for the WMI event to be generated. After the event has been generated, I know that it is safe to start the service back up again:
Stop-Service -Name w32Time
Wait-Event -SourceIdentifier stopped
Start-Service -Name w32Time
The last thing to do is to clean up a little bit by unregistering the event consumer and deleting the events:
Unregister-Event -SourceIdentifier stopped
Remove-Event -SourceIdentifier stopped
} # end invoke-command
When I am finished doing that, I remove the Windows PowerShell session by using the Remove-PSSession cmdlet as shown here:
Remove-PSSession -Session $psSession
Regedit can be used remotely to view registry keys in Hkey_Local_Machine and in Hkey_Users. Some of the registry settings modified by the script are seen in the following image.
If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments