Summary: Learn how to use a Windows PowerShell cmdlet to determine if the time zone on remote servers has been changed from the default.
Microsoft Scripting Guy, Ed Wilson, is here. One of the cool things about the Scripting Wife is that from time to time I can ask her if she would like to help with some of the system admin duties around the house. Of course, on these occasions she is more than delighted to show off her scripting skills. Take for example, a situation I ran across today. I was working with one of my servers, comparing different event log entries among machines, when I noticed what appeared to be a time skew. I checked, and noticed that I had forgotten to set the time zone when I built the computer. This made me curious…did I forget to do this on other servers on the network?
Detecting time zone settings on servers
There are several ways to approach this problem, including using Windows Management Instrumentation. But I decided to use the Get-WinEvent cmdlet and check the DateTimeControlPanel operational trace log. This is because an event gets written to this trace log when the time zone is set. If the time zone is never set, there is no entry in this trace log.
Note This log is automatically enabled on server operating systems beginning with Windows Server 2008 R2. The trace log exists, but it is not enabled on Windows Server 2008. It is also available, but not enabled on client operating systems beginning with Windows Vista.
The DateTimeControlPanel trace log on one of my servers running Windows Server 2008 R2 is shown in the image that follows.
Use PowerShell to query the DateTimeControlPanel log
I decide to ask the Scripting Wife to join me, so she can help check all the servers on the network to determine the time zone settings. I grab my Windows 7 phone, and send the following SMS message.
“Would you like to come to my office and help me check the time zone settings on a bunch of servers?”
It seems like I just completed hitting send, and she was standing in the doorway to my office.
“You rang?” she asked, sounding a bit like Lurch.
“I just found out that I omitted setting the time zone on some of the new servers I built last weekend,” I started to explain.
“And that affects me how?” she asked.
“Well, it really does not. But I thought it would be a great time to give you some real-world practice reading trace logs,” I explained. “I can tell you for a fact, it will be a useful skill to have for the 2012 Scripting Games.”
“Well then, why didn’t you just say so?” she exclaimed.
“I just did.”
She just waved an impatient hand towards me that I think indicated I was to clear my chair to provide her with premium seating in front of the array of monitors that occupy my desk.
“So get on with it. I don’t have all day,” she said, “I have important things to do this afternoon.”
“OK. We need to run a command on a bunch of remote servers. To do this, what cmdlet will we use?”
“The Invoke-Command cmdlet will do that. Is that what you wanted to know?”
“Exactly. Now, to read from a trace log, what cmdlet do you use?”
“You know. You sound a lot like your new Windows PowerShell quiz.”
“Of course I do. I wrote it. Just answer the question and quit stalling.”
“Well, I guess I could use the Get-WinEvent cmdlet. By the way, why is it called Get-WinEvent instead of Get-EventLog?”
“Because we already had a cmdlet named Get-EventLog. That’s what happens when all the good names are taken.”
“Oh,” she said looking like she was not certain that I was being serious, “Then why don’t we just use the Get-EventLog cmdlet to query all of the trace logs?”
“Because Get-EventLog only works on classic event logs, not the ETW trace logs.”
“Oh. OK. Then why don’t we just use the Get-WinEvent cmdlet to do everything? I know it has a Credential parameter, and it also has a ComputerName parameter.”
“Because the Get-WinEvent requires that a port be open in the firewall for the event log service. In addition, I cannot supply an array to the ComputerName parameter of that cmdlet.”
“Well, then let’s get this show on the road. Show me what I need to know,” she said.
“First of all, you need to use the Invoke-Command cmdlet to run the command on the remote computers. Use the cn.txt file that lists all of the servers. Next, you will need to use the Get-WinEvent cmdlet inside the script block to do the actual query. I have the credentials stored in the $cred variable. While you are at it, create an easy-to-read table that lists the computer name, the time of the message, and the actual message,” I said.
The Scripting Wife thought for a few seconds, and then typed the following command. (The command is a single-line command that wraps, but it does not include any line continuation characters.)
invoke-command -cn (gc c:\fso\cn.txt) -cred $cred {Get-WinEvent -LogName
Microsoft-Windows-DateTimeControlPanel/Operational -Force} | select pscomputername, timecreated, message | ft pscomputername, timecreated, message -AutoSize -Wrap
The command runs for nearly a minute. When it completes, the output appears as in the image that follows.
“Connect to the remote computer by using RDP and make the change,” I said.
The time settings dialog box is shown in the following image.
“But why do I have to use RDP to connect to the server just to set the time zone? I don’t want to be a button monkey, I am a Scripting Wife,” she said emphatically.
“OK, Dudette. Chill please,” I said. “You are right. It is entirely possible to get and set the time zone information by using a simple command-line utility tool. Keep in mind that this utility tool works on Windows7 and Windows Server 2008 R2; therefore, it will work on the machine running Windows Server “8” Beta that you discovered.”
“So don’t keep me in suspense…Give,” she said.
“The command is tzutil. To get a time zone, use the /g parameter. To set the time zone use the /s parameter and specify the time zone. I like to use the /g parameter after I have used /s to set a new time zone.”
“So does the tzutil command have a /c parameter for ComputerName?” she asked.
“Nope. But this is where the Invoke-Command cmdlet comes in handy,” I said, “Go ahead and set the new time zone on the server running Windows Server “8” Beta to Eastern Standard Time.”
The Scripting Wife thought for about a minute, and then she typed the following command.
invoke-command -cn w8server6 -cred $cred {tzutil /s "Eastern Standard Time"}
“Very good,” I said, “Now use the tzutil command to verify that the change took place.”
The Scripting Wife used the Up arrow to retrieve her previous command, and she edited the line until it looked like the following.
invoke-command -cn w8server6 -cred $cred {tzutil /g}
“Perfect.”
“I have just one question for you,” she said.
“If I could have used the tzutil command, why did you have me parsing the DateTimeControlPanel log?” she asked.
“Because I wanted to show you that you could. Also it actually made it easier because the only time an entry existed was if the time zone actually had been changed. Remember, there were no entries in the log for Windows Server “8” Beta because it was still at the default Pacific Standard Time setting,” I explained.
“Yes, I guess that makes sense,” she said somewhat hesitantly.
And with that, she got up and departed.
That is about all there is to using the Get-WinEvent cmdlet to connect to a group of remote computers and determine if the time zone is configured on the machines. Scripting Games 2012 Prep Week will continue tomorrow.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy