Monday, March 8, 2010

Converting time formats in Powershell

Since I am spending the morning looking at solutions to track down lockout events to source in a more automated fashion, I'm stuck looking at how to dig through event log events. Using the Active Directory values for bad password time helps to locate a domain controller with useful log events, but the format needs some adjustment. When looking at AD, the format can look like this:

lastlogontimestamp {129121380931028667}
badpasswordtime {129115363568077019}

In powershell it is very easy to convert this to a datetime object for further use. If you want to just display the value in a readable format, you can just use this command. If you want to work with it some more, assign it to a variable:



PS C:\> [datetime]::fromfiletime(129121380931028667)

Wednesday, March 03, 2010 7:01:33 PM

Now when looking at event logs with something such as WMI queries, the date time format is different.

The System.Management.ManagementDateTimeConverter class can be used to convert between WMI's format and DateTime.

Once the value is in WMI format, into a wmi queries. If you are searching logs in a timewritten range you may want to adjust the seconds of this value +/- a few to help ensure that everything links up. You can also drop the milliseconds as the AD time stamp may not perfectly match up to a system event log time stamp. In any case, having a tight time range and very specific WMI query will help keep remote event log search queries fast and leave you will less results to process in any addition work you plan to do.

Some basic code using these conversions and providing a time range for event log searches:

function wmiTime-toDateTime([string]$wmitime){
#YYYYMMDDHHMMSS.000000-UUU where -UUU is the three-digit offset
return []::todatetime($wmitime)


function dt-toWmiTime([system.datetime]$dt) {
#YYYYMMDDHHMMSS.000000-UUU where -UUU is the three-digit offset
$dt = $dt.touniversaltime()
$wmiformat = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($dt)
return $wmiformat


function adtime-toWMItime([string]$mydatetime) {
$dt = [datetime]::FromFileTime($mydatetime) 
$wmitime =  dt-toWmiTime $dt
return $wmitime

function adjust-wmitime ([string]$wmiOrigTime, [double]$secondOffset) {
#WMI time format: YYYYMMDDHHMMSS.000000-UUU where -UUU is the three-digit offset
#This function takes an original time and provides an array of two values, search start time and
#search end time

$mybasetime = wmiTime-toDateTime $wmiOrigTime
$myadjustedDT = $mybasetime.addseconds($secondoffset)
$myResultingWMI = dt-toWmiTime $myadjustedDT
return $myResultingWMI


function compare-wmiTimes($startTime,$endTime) {
 $dtS = wmiTime-toDateTime $startTime
 $dtE = wmiTime-toDateTime $endTime
 $timediff = new-timespan -start $dtS -end $dtE
 if ($timediff.TotalMilliseconds -gt 0) {
  #second date is later than the first
  return 1
 } elseif ($timediff.TotalMilliseconds -eq 0) {
  #time is the same
  return 0
 } else {
  #first date is later than the second
  return -1


function wmitime-timerange ([string]$wmiOrigTime, $secondOffset) {
$secondoffset = [double]$secondoffset
$mystartWMI = adjust-wmitime $wmiOrigTime -$secondoffset
$myendWmi = adjust-wmitime $wmiOrigTime $secondoffset
$myResult = ($mystartWMI, $myendWMI)
return $myResult

No comments:

Post a Comment