Hey, Scripting Guy! Weekend Scripter: Configuring W32Time Service Logging

ScriptingGuy1

Bookmark and Share

 

Microsoft Scripting Guy Ed Wilson here, yesterday I wrote a script that configured my domain controller with an external time source. After doing that, I thought it would be a good idea to have the ability to enable and disable diagnostic logging for the W32Time service. I ran across a pretty good knowledge base article, KB 816043, that explained the different registry keys that needed to be modified, and I decided to get to work on the script. (I later found the Time Service team blog on MSDN that talks about a different way to do this). The result is the ConfigureW32TimeLogging.ps1 script seen here.

ConfigureW32TimeLogging.ps1

Param(
  $computer = “Hyperv”,
  $user = “nwtraders\administrator”,
  [switch]$enable,
  [switch]$disable
)

Function Start-W32TimeLogging($PSSession)
{
 Invoke-Command -Session $PSSession -ScriptBlock {
 $timeRoot = “HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Config”
 $invalidChars = [io.path]::GetInvalidFileNamechars()
 $date = Get-Date -format s
 $file = “w32time-” + ($date.ToString() -replace “[$invalidChars]”,”-“) + “.log”
 $logPath = Join-Path -Path c:\fso -ChildPath $file
 Set-ItemProperty -path “$timeroot” -name FileLogSize -Value 10000000
 Set-ItemProperty -path “$timeroot” -name FileLogName -Value $logPath
 Set-ItemProperty -path “$timeroot” -name FileLogEntries -Value 0-116
 
 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
} #end Start-W32TimeLogging

Function Stop-W32TimeLogging($pssession)
{
 Invoke-Command -Session $PSSession -ScriptBlock {
 $timeRoot = “HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Config”
 Remove-ItemProperty -path “$timeroot” -name FileLogSize
 Remove-ItemProperty -path “$timeroot” -name FileLogName
 Remove-ItemProperty -path “$timeroot” -name FileLogEntries
 
 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
} #end Stop-W32TimeLogging

# *** Entry Point to script ***

$psSession = New-PSSession -ComputerName $computer -Credential $user

if($enable) { start-w32TimeLogging -pssession $pssession ; exit }
if($disable) { stop-w32TimeLogging -pssession $pssession ; exit }

To enable diagnostic logging for the W32Time service, the three registry keys that are shown in the following image are added to the w32Time configuration hive. To disable diagnostic logging, the same three registry keys are removed. Of course, both of these operations require the w32Time service to reload the configuration information from the registry. To do this, I stop and start the w32Time service. 

Image of the three registry keys

The script is extremely similar to the one I wrote yesterday. They both use Windows PowerShell remoting, they both use the Set-Itemproperty cmdlet to create registry keys, and they both use WMI eventing to indicate when the w32Time service has stopped.

Despite the similarities, there are some differences between the two scripts. One of the things I do is create a custom name for the w32Time.log file. I do this because I might want to run it at different times of the day on the same day, and I did not want to fool with renaming or deleting pre-existing log files. This will also automatically allow me to keep as many logs as I wish. Here is the code:

$invalidChars = [io.path]::GetInvalidFileNamechars()
$date = Get-Date -format s
$file = “w32time-” + ($date.ToString() -replace “[$invalidChars]”,”-“) + “.log”
$logPath = Join-Path -Path c:\fso -ChildPath $file

Because I am using the timestamp that gets converted to a string as part of the file name, I need to do a little bit of work. This is because all of the characters that are used in a timestamp are not allowed to be used in a filename. Using the GetInvalidFileNameChars static method from the system.io.path .NET Framework class, I can easily find out which characters are disallowed. I use this character set, and feed it to the replace operator to change all invalid characters to a dash. Finally the Join-Path cmdlet is used to build the path to the new log file.

The log itself is Unicode, so when you attempt to read it, you will need to specify the encoding parameter. Using the Select-String cmdlet, I can read the file and look for a particular string at the same time. The command I used is seen here (I shortened the path to fit it on a single line for clarity):

Select-String -Path c:\time.log -Pattern “ntpclient” -Encoding unicode –AllMatches

When I run the command, I am greeted with the output seen in the following image.

Image of output from the command

 

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

Discussion is closed.

Feedback usabilla icon