Printer Friendly Version      Send     
Click to Rate and Give Feedback
Also by this Author

Looking for an easier way to add terms to the Microsoft Word dictionary without doing it by hand, one word at a time? Who isn't? This month, the Scripting Guys show you how to create custom dictionaries in Microsoft Word, and how to programmatically configure Word to use those dictionaries.

The Microsoft Scripting Guys

TechNet Magazine June 2007

...

Read more!

Ever wonder how you could send values to and from a dialog box in an HTML Application (HTA)? Here’s an explanation of how to create a dialog box and then pass information back and forth between the dialog box and the main HTA.

The Microsoft Scripting Guys

TechNet Magazine May 2007

...

Read more!

The AllSigned execution policy provides the most secure Windows PowerShell environment. So how do you sign your Windows PowerShell scripts? Don Jones shows you how.

The Microsoft Scripting Guys

TechNet Magazine April 2008

...

Read more!

The Scripting Guys discuss Socrates and revisit the topic of querying an XML file . This time, however, the XML file is structured so that rather than using child nodes, additional property values are configured as attributes.

The Microsoft Scripting Guys

TechNet Magazine October 2008

...

Read more!

This month, The Scripting Guys take a close look at the WMI infrastructure. Along the way, they provide some helpful scripts that can serve as a starting point for learning more and accomplishing useful administrative tasks.

The Microsoft Scripting Guys

TechNet Magazine November 2008

...

Read more!

Popular Articles

Far too often, people who are not trained database administrators somehow end up responsible for a database. They lack the proper training and knowledge to maintain their database, and problems begin to develop. Here’s a primer for all those involuntary DBAs who need a crash course in database maintenance best practices.

Paul S. Randal

TechNet Magazine August 2008

...

Read more!

How do you secure the desktop against malicious ActiveX controls without limiting application compatibility? We’ll take you on a tour of the ActiveX Installer Service (AxIS) in Windows Vista that addresses this issue with a new way to manage ActiveX controls.

Rob Campbell and Joel Yoker

TechNet Magazine July 2007

...

Read more!

Many organizations rely on ISA Server 2006 to secure their environment, but few take the important step of securing ISA Server itself. Here’s a guide to using the Security Configuration Wizard and Administrative roles to limit its attack surface and secure your ISA Server 2006 implementation.

Alan Maddison

TechNet Magazine September 2008

...

Read more!

The introduction of Hyper-V makes virtualization an even more compelling solution for IT environments. Get an overview of today’s virtualization market and see how Hyper-V improves the manageability, reliability, and security of virtualization

Rajiv Arunkundram

TechNet Magazine October 2008

...

Read more!

The new version of SQL Server offers a host of new features and enhancements that promise to improve performance, increase security, and make life better for database administrators. Here’s an overview of the key changes and what you can expect from SQL Server 2008.

Randy Dyess

TechNet Magazine April 2008

...

Read more!

Our Blog

In the era of Software-plus-Services, Web services play an important role because they decouple hosted back-end environments from on-premise front-end applications. Explore  how the SharePoint platform drives online collaboration, so that Office applications and add-ins can run on local workstations while Web ...

Read more!

Proxy authentication lets users perform a simple bind to an Active Directory Lightweight Directory Services instance but still have an association to an Active Directory account. This can be very useful: it gives developers full access to a user object without giving them access to the Active Directory account, and it allows products that require the X.500 format to be used with Active Directory. ...

Read more!

The December 2008 issue of TechNet Magazine is now available online. And it's filled with information about interop.

Find out how to integrate Linux clients with ...

Read more!

"For developers, one difficult problem in SQL Server is tracking what data has changed in a database. An even greater challenge is architecting a simple solution that doesn’t heavily impact workload performance and isn't difficult to create, implement, and manage. So why go to all the trouble to track changes? Is tracking changes really worth all this effort? Two commonly cited examples are to support updates to a data warehouse and to support the synchronization of heterogeneous, occasionally connected systems." ...

Read more!

The complexity of systems today makes troubleshooting more difficult than ever. It’s harder to keep track of what has changed, when, and how that relates to everything else. If something goes wrong, chances are good that users will have a hard time figuring out what has changed on their computers, whether due to updates, new software, ...

Read more!

Hey, Scripting Guy! It’s About Time (Oh, and About Dates, Too)
The Microsoft Scripting Guys

Download the code for this article: ScriptingGuy2006_07.exe (151KB)

You know, the Scripting Guys hardly ever wax philosophical. (We hardly ever wax our cars or our floors, either, but that’s a different story.) When it comes to the nature of time, however, well, in that case we just can’t help ourselves. That’s because time is such an interesting phenomenon. After all, you can call time, cheat time, make time, waste time, steal time, and keep time; heck, you can even kill time. (Disclaimer: no time was harmed in the making of this column.) Time flies, time marches on, and time (not to mention tide) waits for no man. And yet, time is on your side and time heals all wounds, even though there’s no time like the present and definitely no time for sergeants. We could go on, but we simply don’t have the time.
OK, that’s not true. We actually have lots of time. It’s just that the editors of this magazine have certain expectations, one of them being that a scripting column should include information about scripting. Although, considering what they pay us, they should be happy to get any kind of column. Haven’t they ever heard the expression "time is money"?
Unfortunately, there is something you can’t do with time, at least not easily: make any sense of it in a Windows® Management Instrumentation (WMI) script. For example, consider this simple little script, which tells you the date and time that the operating system was installed on a computer (the value of the InstallDate property):
strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & _
    strComputer & "\root\cimv2")

Set colOperatingSystems = _
    objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")

For Each objOperatingSystem in _
    colOperatingSystems
    Wscript.Echo objOperatingSystem.InstallDate 
Next
So when was the operating system installed on this computer? Why, on the date shown in Figure 1, of course. Ah, yes: 20031121093604.000000–480. What a great time we had back then, eh? Remember when that one guy did that one thing? Precious memories...
Figure 1  
Actually, this is a valid date and time: 9:36 A.M., November 21, 2003. And, no, the date and time isn’t being stored in, say, Klingon format. Instead, WMI stores dates and times in the Universal Time Coordinate (UTC) format. We won’t explain the details of the UTC format here; for more information, read the WMI chapter in the Microsoft® Windows Scripting Guide. Suffice it to say that the InstallDate property returns the date in a valid date-time format. Furthermore, you can use code similar to this function to convert a UTC date-time value to a regular date-time value:
Function WMIDateStringToDate(dtmInstallDate)
    WMIDateStringToDate = _
        CDate(Mid(dtmInstallDate, 5, 2) &_
        "/" &_
        Mid(dtmInstallDate, 7, 2) &_
        "/" &_
        Left(dtmInstallDate, 4) &_
        " " &_
        Mid (dtmInstallDate, 9, 2) &_
        ":" &_
        Mid(dtmInstallDate, 11, 2) &_
        ":" &_
        Mid(dtmInstallDate, 13, 2))
End Function
We know what you’re thinking—this isn’t the most straightforward code you’ve ever seen. (Yes, we know what you’re really thinking, but they won’t let us use words like that in this magazine.)
Oh, and it gets worse. Suppose you want to use WMI to query the event logs for all the events that occurred on 12/19/2005. Can you use the date 12/19/2005 in your WMI Query Language (WQL) query? You wish. Instead, you have to convert 12/19/2005 to its UTC equivalent (something on the order of 20051219000000.000000–480). How nice...
We’re sure by this point you’re wondering, "Man, if those WMI guys are so smart, why can’t they come up with a way to do these conversions for us, and without us having to use Mid and Left and all those other crazy VBScript functions?" Well, it turns out that they did. In Windows XP and Windows Server™ 2003 (sorry, Windows 2000 users, but this enhancement isn’t available on operating systems that predate Windows XP), WMI includes a new object—the SWbemDateTime object—that makes it a snap to convert a UTC date-time value to a regular old date-time value. And vice versa.
No, we’re not pulling your leg; it’s true. To prove it, let’s take a look at a sample script that retrieves the date and time at which the operating system was installed and then reports that information back as a real date-time value.
As you can see in Figure 2, this script is similar to the first script we showed you—the script that reported back the InstallDate as a UTC value. In fact, there are only a couple of differences here. To begin with, we create an instance of the WbemScripting.SWbemDateTime object. As you might have guessed, this gives us an instance of the SWbemDateTime object we can work with:
Set objSWbemDateTime = _
    CreateObject("WbemScripting.SWbemDateTime")
Set objSWbemDateTime = _
  CreateObject("WbemScripting.SWbemDateTime")

strComputer = "."
Set objWMIService = GetObject( _
    "winmgmts:\\" & _
    strComputer & _
    "\root\cimv2")

Set colOperatingSystems = _
    objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")

For Each objOperatingSystem _
    in colOperatingSystems
    objSWbemDateTime.Value = _
        objOperatingSystem.InstallDate
    Wscript.Echo _
        objSWbemDateTime.GetVarDate(False)
Next
The other difference is that we now use two lines of code to retrieve, convert, and report back the install date. First, we assign the UTC date-time value returned by InstallDate to the Value property of the SWbemDateTime object. That’s what we do here:
objSWbemDateTime.Value = _
    objOperatingSystem.InstallDate
Why do we have to do this? Well, when we create an SWbemDateTime object we create a blank object—the object’s properties, such as Value, are all null. Here we’re just assigning a UTC value to our object: the value of the InstallDate property.
All we have to do now is call the GetVarDate method. This converts the UTC value to a regular old date-time value (or, more correctly, a variant date-time value). To keep the coding to a minimum, we echo back this value at the same time we convert it:
Wscript.Echo objSWbemDateTime.GetVarDate(False)
Alternatively, we could have stashed this value in a variable:
dtmMyDate = objSWbemDateTime.GetVarDate(False)
And what do we get when we run this script? We get the output shown in Figure 3.
You’re right: it is about time, isn’t it? Some of you noticed the False parameter that we passed to the GetVarDate method. As it turns out, GetVarDate can report back the date and time in one of two ways: correcting for the local time zone or without correcting for the offset (difference) between local time and Greenwich Mean Time (technically, a somewhat nebulous time known as "unzoned time"). What does that mean? Well, suppose we set this parameter to True. In that case, we’ll get back the value shown in Figure 4.
Figure 3  
Figure 4  
Why the difference? This computer happens to be based in Redmond, WA (the center of the universe), and Redmond time is eight hours behind Greenwich Mean Time. (For a more detailed discussion of local time and unzoned time, see the CIM_DATETIME section of the WMI SDK.) To report the value as Redmond time (or whatever your local time happens to be) set the parameter to True.
Unless, of course, you’re running Windows XP Service Pack 1 (SP1) or "plain-vanilla" Windows XP. Setting the parameter to False under these OSs gives you the corrected time. That’s actually the opposite of what it should do; because this parameter corrects for local time, you’d expect to set it to True to get local time. That’s the case in Windows XP SP2 and Windows Server 2003. With these operating systems, this has been "fixed" and you set the parameter to True in order to correct for local time.
That could pose a problem if you have some computers running Windows XP SP1 and others running Windows XP SP2. In that case, you’ll have to add a bit of logic to check which version of Windows you’re running and then set the value of the parameter accordingly. But hey, if it didn’t have some quirkiness, it wouldn’t be scripting, would it?
Now, what about going the other direction? That is, what about taking a variant date and converting it to a UTC value? Figure 5 shows a script that retrieves a collection of all the event log events recorded on or after January 1, 2006 (that is, all events where the TimeWritten property is greater than or equal to 1/1/2006). To do so, it takes a variant date (1/1/2006), converts that date to a UTC date-time value, and then uses that value in the WQL query.
Set objSWbemDateTime = _
  CreateObject("WbemScripting.SWbemDateTime")

objSWbemDateTime.SetVarDate #1/1/2006#, True

strComputer = "."

Set objWMIService = GetObject(_
    "winmgmts:\\" &_
    strComputer &_
    "\root\cimv2")

Set colEvents = objWMIService.ExecQuery _
    ("Select * from Win32_NTLogEvent _
    Where TimeWritten >= ‘" & _
    objSWbemDateTime.Value & "’") 

For Each objEvent in colEvents
    Wscript.Echo objEvent.TimeWritten
Next
As you can see, this is even easier than converting a UTC date to a regular date. After creating an instance of the SWbemDateTime object, we use one line of code to set the Value of the object to 1/1/2006:
objSWbemDateTime.SetVarDate #1/1/2006#, True
That’s it—we simply call the SetVarDate method, passing the date (enclosed within # characters, which ensures that VBScript treats the value as a date) and the parameter True. Note that in this case—unlike GetVarDate—True really does mean "Yes, convert this date to local time." That means you can use the same value in Windows XP SP1, Windows XP SP2, and Windows Server 2003.
You probably want to convert the time to local time. After all, we’re using this value in a WQL query that retrieves events written to the event log where the TimeWritten for the event is greater than or equal to the zero-hour on 1/1/2006. If we don’t correct the time for local time, we could end up getting events that were written as many as eight hours prior to the zero-hour, which means we could end up with some events that actually occurred on New Year’s Eve (12/31/2005). Needless to say, many of us don’t want to know what happened on New Year’s Eve, if you catch our drift.
If this is confusing, try running the script twice, once with the parameter set to True and once with the parameter set to False. If you compare the results, you’ll see what we’re talking about.
Now that we’ve converted our date to a UTC date, we can use the Value of our SWbemDateTime object in our WQL query, like this:
Set colEvents = objWMIService.ExecQuery _
    ("Select * from Win32_NTLogEvent _
    Where TimeWritten >= ‘" & _
    objSWbemDateTime.Value & "’")
Cool, huh?
Now, admittedly, we chose a pretty easy case here—any event that occurred after the year 2005. We could get a bit fancier and retrieve only events that occurred between 2:00 P.M. on January 1st and 6:00 P.M. on January 3rd. But that’s a tad bit more complicated and something we’ll have to address later on; after all, right now we really are out of time.

Parting Words
Before we go, we’d like to remind you of the words of author and activist Louise Hart: "The best thing to spend on your children is your time." Maybe that’s true, but we’re willing to bet there were some awfully disappointed kids at the Hart household last Christmas morning.
A Note from the Scripting Guys
If you’re walking down the street and you see a crowd of people looking up at the sky, do you stop and look? Of course you do. Even if you’re trying not to, you still take a subtle peek. On the one hand, this could be some sort of human behavior study and you’ve just responded as an obedient guinea pig. On the other hand, there could be a UFO hovering overhead and you certainly don’t want to miss the first sight of life from another planet. Or there could be something dangling from a crane, ready to fall on your head if you don’t watch out. Whatever the reason, your curiosity will typically get the better of you and you’ll look.

Take a Look
That brings us to the Script Center. Why are system administrators flocking to the Script Center and looking around? Come find out for yourself. Chances are nothing will fall on your head if you don’t, but you could still eliminate a certain amount of pain from your life if you do.
The Script Center is overflowing (can a Web site overflow?) with resources to help you automate your Windows systems. In addition to thousands of scripts, you’ll find daily Q & A articles (that answer actual user questions), puzzles to improve your troubleshooting skills, and even something called Dr. Scripto’s Fun Zone. (Missing the Fun Zone would be like missing the UFO. OK, not exactly like that, but close.) All of this is meant to educate you and help you become more efficient at your job—and here’s the important part—without putting you to sleep in the process. It’s one of those "you have to see it to believe it" things.

Tell Me Something I Don’t Know
Now you’re waiting for us to throw in some steak knives for just $19.99, aren’t you? Well, that’s not going to happen. (We’re usually not allowed to handle sharp objects.) But here are some new things we can provide:
  • Information about the new scripting capabilities of Windows Vista.
  • New articles every day and a new puzzle each week.
  • New scripts in the Community-Submitted Scripts Center provided by your fellow script writers. (You can even submit your own scripts that you’d like to share.)

Celebrate!
And finally, join us in July as we celebrate the 500th episode of Hey, Scripting Guy! For complete details on the celebration (and maybe even some prizes), visit us at microsoft.com/technet/scriptcenter.


The Microsoft Scripting Guys spend most of their time at the beach...oh, um, no, we mean: The Scripting Guys are hard-working members of the Microsoft Windows Server User Assistance team. To find out more, go to "About The Scripting Guys".
© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker