Hey, Scripting Guy! I need to understand how to work with dates that I receive from Windows Management Instrumentation (WMI). I remember in VBScript I had to use a function I got from the Scripting Guys that did string manipulation to convert the WMI date to a “normal” date. I guess that is okay, but I had no idea how that function worked or how to correct things when it did not work properly. I have been reading your Hey, Scripting Guy! Blog posts this week about dates, and I have yet to see you address this issue. Is it because it is too hard, and you are going to do the old two-step shuffle? — EA Hello EA, Microsoft Scripting Guy Ed Wilson here. As a famous twentieth century philosopher once said, “I can’t dance”; therefore, I do not know how to do the old two-step shuffle. Or the Ickey Shuffle. I’m not too bad with the Corgi Shuffle though. I can do a pretty effective string shuffle. It is string shuffling that is required to make sense of the date string that is returned by WMI. This is because WMI dates are returned as strings and not as datetime objects. These strings are compliant with the Distributed Management Task Force (DMTF) Common Information Model (CIM) standards. In VBScript days, most scripters used a version of the function found in the Convert WMI Date-Time Values script in the Scripting Guys Script Repository. EA, you are probably talking about this VBScript function in your email. It was a brilliant piece of code and is shown here:
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
Interestingly enough, in Windows XP a new COM object was introduced to WMI—the SwbemDateTime object. This object obsoleted the WMIDateStringToDate function. This object is discussed in a Hey, Scripting Guy! TechNet Magazine article called It’s About Time (Oh, and About Dates, Too). To use the SwbemDateTime object, I wrote the FunDate function, which is much easier to understand and is more reliable—and perhaps fun!
Function funDate(wmiDate)
Dim objSWbemDateTime
Set objSWbemDateTime = CreateObject(“WbemScripting.SWbemDateTime”)
objSWbemDateTime.value = wmiDate
funDate = objSWbemDateTime.GetVarDate
End function
An example of a WMI UTC date is seen here from the InstallDate property of the Win32_OperatingSystem WMI class.
PS C:> $os = Get-WmiObject win32_operatingsystem
PS C:> $os.InstallDate
20091024192037.000000-240
PS C:>
Either of these approaches can be leveraged in Windows PowerShell. To use the SwbemDateTime object, use the New-Object cmdlet to create an instance of the object. Use the Get-WmiObject cmdlet to perform the WMI query of the Win32_OperatingSystem class, supply the InstallDate value to the value property of the SwbemDateTime object, and call the GetVarDate method from the same object. This technique is illustrated here:
PS C:> $swbem = New-Object -ComObject wbemscripting.swbemdatetime
PS C:> $os = Get-WmiObject win32_operatingsystem
PS C:> $swbem.Value = $os.InstallDate
PS C:> $swbem.GetVarDate()
Saturday, October 24, 2009 7:20:37 PM
PS C:>
But the System.Management.ManagementDateTimeConverter .NET Framework class contains a number of static methods that are useful for working with WMI Dates. The static methods are shown here:
PS C:> [management.managementDateTimeConverter] | gm -s
TypeName: System.Management.ManagementDateTimeConverter
Name MemberType Definition
—- ———- ———-
Equals Method static bool Equals(System.Object objA, System.Objec…
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, Sys…
ToDateTime Method static System.DateTime ToDateTime(string dmtfDate)
ToDmtfDateTime Method static string ToDmtfDateTime(System.DateTime date)
ToDmtfTimeInterval Method static string ToDmtfTimeInterval(System.TimeSpan ti…
ToTimeSpan Method static System.TimeSpan ToTimeSpan(string dmtfTimespan)
PS C:>
To parse the InstallDate property from the Win32_OperatingSystem WMI class, you would use the ToDateTime static method as illustrated here:
PS C:> $os = Get-WmiObject win32_operatingsystem
PS C:> [management.managementDateTimeConverter]::ToDateTime($os.InstallDate)
Saturday, October 24, 2009 7:20:37 PM
PS C:>
This can be accomplished in one line, by retrieving both the WMI class and selecting the property at the same time.
There is only one problem with using the management.managementDateTimeConverter .NET Framework class—it is waaaaaaaaaaay toooooooooooo loooooong for me to type reliably on a regular basis. Therefore, this makes a great candidate to add to one’s profile. Before I add anything to a profile, I like to test the command first to ensure it works. Here is the command and the “test”:
PS C:> New-Variable -Name dteConv -Value $(“management.managementDateTimeConverter”
-as [type]) -Description MrEd_Variable
PS C:> $dteConv::ToDateTime((gwmi win32_operatingSystem).InstallDate)
Saturday, October 24, 2009 7:20:37 PM
PS C:>
I can edit a Windows PowerShell profile in Notepad, as shown in the following image. (Windows PowerShell profiles were discussed in Hey, Scripting Guy! Blog posts during Profile Week.)
There is another way to deal with WMI dates and times, and that is to use a ScriptMethod that is added by the Windows PowerShell team to WMI objects. Two ScriptMethods are added, as shown via the Get-Member cmdlet:
PS C:> Get-WmiObject win32_OperatingSystem | Get-Member -MemberType ScriptMethod
TypeName: System.Management.ManagementObject#rootcimv2Win32_OperatingSystem
Name MemberType Definition
—- ———- ———-
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime ScriptMethod System.Object ConvertToDateTime();
PS C:>
Because the ScriptMethods are added directly to instances of the WMI class, they can be accessed directly:
PS C:> $os = Get-WmiObject win32_OperatingSystem
PS C:> $os.ConvertToDateTime($os.InstallDate)
Saturday, October 24, 2009 7:20:37 PM
PS C:>
Using the ScriptMethod always involves two steps: creating an instance of the WMI object, and passing an instance with the property to the ScriptMethod. The only way to perform this on a single line is to use the semicolon to create two logical commands on a single physical line. This is shown here:
PS C:> $os = Get-WmiObject win32_OperatingSystem ; $os.ConvertToDateTime($os.Install
Date)
Saturday, October 24, 2009 7:20:37 PM
PS C:>
The advantage of always having access to the ConvertToDateTime ScriptMethod on an instance of a WMI class can be seen here. The gwmi alias for the Get-WmiObject cmdlet and the ft alias for the Format-Table cmdlet are used. A custom label is created for the table called “Installed”. The value of the installed date is created by using the ConvertToDateTime ScriptMethod. The results can be compared to creating a table with the version and the installdate without parsing the date:
PS C:> gwmi win32_operatingsystem | ft version, @{LABEL=”Installed”; EXPRESSION = {$
_.convertToDateTime($_.InstallDate)}}
version Installed
——- ———
6.1.7600 10/24/2009 7:20:37 PM
PS C:> gwmi win32_operatingsystem | ft version, installDate
version installDate
——- ———–
6.1.7600 20091024192037.000000-240
PS C:>
EA, that is all there is to using dates when working with Windows Management Instrumentation (WMI). That also brings Date Week to a close. Join us tomorrow for Quick-Hits Friday.
We invite you to follow us on Twitter or Facebook. If you have any questions, send email 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