Powershell use Get-WinEvent with hashtable to query very specific time range

active-directorypowershellwindows-event-log

I'm trying to make a powershell script that essentially automates the account lockout tools.
ideally I'll be able to get a fairly efficient query that can identify recently locked out accounts then retrieve that data from our DC's and probably send an email letting us know who was locked out and a copy of the "message" from the security log.

here's what I have so far:
I read that to use Get-WinEvent we have to use a hashtable so i created a hashtable object and expanded by datetime variables into the hashtable and they appear correct, and if I run something like $hash.starttime | gm , I can confirm that it's still a system.datetime object.

$LockedOut = Get-ADUser -Properties AccountLockoutTime,LastBadPasswordAttempt,BadPwdCount,LockedOut  -Filter * | ?{$_.AccountLockOutTime -ge (Get-Date).AddHours(-3)}
$LockedOut | ft name,samaccountname,LockedOut,AccountLockoutTime,BadPwdCount,LastBadPasswordAttempt
$DomainControllers = Get-ADDomainController -Filter *   

ForEach($lockeduser in $LockedOut)
{
$lockeduser.Name
ForEach($DC in $DomainControllers.name)
    {
    $before = ($lockeduser.AccountLockoutTime.AddMinutes(1)).date
    $after = ($lockeduser.AccountLockoutTime.AddMinutes(-1)).date
    $hash = $null
    $hash =  @{}
    $hash.Add("Logname", "security")
    $hash.Add("Starttime", $after)
    $hash.Add("Endtime", $before)
    $DC
    $messagecriteria = $lockeduser.Name
    $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_.Message -like "*$messagecriteria*"}
    $message
    }
    "----------------------------------------------------------------------------------------------------------"
}

But when I run the query I only get back

Get-WinEvent : No events were found that match the specified selection criteria.
At line:19 char:20
+         $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_ ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (:) [Get-WinEvent], Exception
+ FullyQualifiedErrorId : NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand

Best Answer

I seem to have gotten it to work. I think some variable properties were sticking in memory and it was causing the query to supply the wrong timeframes.

here's the finished product for anyone interested, query has been tightened up to only pull 2 sec worth of logs to parse, and only looking back the last 10 min. There's also an segment for writing the results to a custom PSobject which is useful for exporting to CSV or HTML.

the only thing left is I'll insert and HTML header and have this write to a table that will come across in an email.

$LockedOut = Get-ADUser -Properties AccountLockoutTime,LastBadPasswordAttempt,BadPwdCount,LockedOut  -Filter * | ?{$_.AccountLockOutTime -ge (Get-Date).AddMinutes(-10)}
$LockedOut | ft name,samaccountname,LockedOut,AccountLockoutTime,BadPwdCount,LastBadPasswordAttempt
$DomainControllers = Get-ADDomainController -Filter *   
$results = $null 
ForEach($lockeduser in $LockedOut)
{
$lockedusername = $lockeduser.name
ForEach($DC in $DomainControllers.name)
    {

    $starttime = $lockeduser.AccountLockoutTime.AddSeconds(-1)
    $endtime = $lockeduser.AccountLockoutTime.AddSeconds(1)
    $hash = $null
    $hash =  @{}
    $hash.Add("Logname", "security")
    $hash.Add("Starttime", $starttime)
    $hash.Add("Endtime", $endtime)
    "$lockedusername -  Locating Events between $starttime and $endtime on $DC..."
    $messagecriteria = $lockeduser.Name
    $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_.Message -like "*$messagecriteria*"}
    $message |ft @{Expression={$ExecutionContext.InvokeCommand.ExpandString($lockeduser.Name)};Label="Name"}, `
    @{Expression={$ExecutionContext.InvokeCommand.ExpandString($lockeduser.SamAccountName)};Label="SAMID"},machinename,TimeCreated,ID,message
    $hash.Clear()
    $TC = $message.timecreated
    $ID = $message.id
    $messagetext = $message.message
    IF($message -ne $null)
        {
        ForEach($line in $message)
        {
        $obj = New-Object -TypeName PSObject
                $obj | Add-Member -NotePropertyName "Name" -NotePropertyValue $LockedUser.name
                $obj | Add-Member -NotePropertyName "SamID" -NotePropertyValue $LockedUser.SamAccountName
                $obj | Add-Member -NotePropertyName "DC" -NotePropertyValue $DC
                $obj | Add-Member -NotePropertyName "TimeCreated" -NotePropertyValue $line.TimeCreated
                $obj | Add-Member -NotePropertyName "Event ID" -NotePropertyValue $line.ID
                $obj | Add-Member -NotePropertyName "Message" -NotePropertyValue $line.message
                [Array]$results += $obj
        }

        }
    }
    "----------------------------------------------------------------------------------------------------------"

}

"Table of results"
$results | ft