Retrieving Logon and Logoff from Event Log .evtx file

Hi,

I trying to get the following script working and need helping as I can’t solve the final issue with my changes.

You can see that if I use Get-EventLog the script works as expected. If I change to Get-WinEvent (which I believe I need to do if I wish to use an older .evtx log from an older computer) then it produces no results even though I’m sure the provider name is correct? Ideas would be greatly appreciated. Thanks all in advance.

function get-logonhistory{
 cls
 $Result = @()
 Write-Host "Gathering Event Logs, this can take awhile..."
 #$ELogs = Get-EventLog System -Source Microsoft-Windows-WinLogon
 $ELogs = Get-WinEvent -FilterHashtable @{Path = "c:\logtemp\System*.evtx"; ProviderName = "Microsoft-Windows-Winlogon"}
 If ($ELogs) 
 { Write-Host "Processing..."
 ForEach ($Log in $ELogs)
 { If ($Log.InstanceId -eq 7001)
   { $ET = "Logon"
   }
   ElseIf ($Log.InstanceId -eq 7002)
   { $ET = "Logoff"
   }
   Else
   { Continue
   }
   $Result += New-Object PSObject -Property @{
    Time = $Log.TimeWritten
    'Event Type' = $ET
    User = (New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])
   }
 }
 $Result | Select Time,"Event Type",User | Sort Time -Descending | Out-GridView
 Write-Host "Done."
 }
 Else
 { Write-Host "Problem with Computer"
 Write-Host "If you see a 'Network Path not found' error, try starting the Remote Registry service on that computer."
 Write-Host "Or there are no logon/logoff events (XP requires auditing be turned on)"
 }
}


get-logonhistory

Sorry I’m not on a Windows PC this afternoon so I cannot double-check this.

But I believe that Get-WinEvents has a parameter call -LogFile so you can do something like this:

Get-WinEvent -LogFile System

Hope this helps.

I didn’t think Get-WinEvent could be used on anything but the current event viewer? I want to be able to take reports from old event viewer log files.

I’ve been working on this and have got the code as far as this

#clear the screen
cls


#$Days = 1
$SYSevents = @()
$SECevents = @()


#get location of folder containing log files
Function Select-FolderDialog
{
    param([string]$Description="SELECT FOLDER CONTAINING SYSTEM.EVTX LOGFILE",[string]$RootFolder="MyComputer")

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
     Out-Null     

    $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
    $objForm.Rootfolder  = $RootFolder
    $objForm.Description = $Description
    $Show = $objForm.ShowDialog()
        If ($Show -eq "OK")
        {
            Return $objForm.SelectedPath
        }
        Else
        {
            Write-Error "Operation cancelled by user."
        }
    
}
$Drive = Select-FolderDialog # the variable contains user folder selection


#System Log save dialog
Function Get-SaveFileSYS
{
    param([string]$Description="SELECT FOLDER TO SAVE SYSTEM REPORT",[string]$initialDirectorySYS="MyComputer")

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
    Out-Null

    $SaveFileDialogSYS = New-Object System.Windows.Forms.SaveFileDialog
    $SaveFileDialogSYS.initialDirectory = $initialDirectorySYS
    $SaveFileDialogSYS.filter = "HTML Files (*.htm)|*.htm"
    $SaveFileDialogSYS.ShowDialog() | Out-Null
    $SaveFileDialogSYS.filename #= "SystemLogsReport"
} 
$SYSresults = Get-SaveFileSYS # the variable contains save file location
#$SYSresults = "c:\logtemp\SystemLogsReport.htm"


#Security Log save dialog
Function Get-SaveFileSEC
{
    param([string]$Description="SELECT FOLDER TO SAVE SECURITY REPORT",[string]$initialDirectorySEC="MyComputer")

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
    Out-Null

    $SaveFileDialogSEC = New-Object System.Windows.Forms.SaveFileDialog
    $SaveFileDialogSEC.initialDirectory = $initialDirectorySEC
    $SaveFileDialogSEC.filter = "HTML Files (*.htm)|*.htm"
    $SaveFileDialogSEC.ShowDialog() | Out-Null
    $SaveFileDialogSEC.filename #= "SecurityLogsReport"
} 
$SECresults = Get-SaveFileSYS # the variable contains save file location
#$SECresults = "c:\logtemp\SecurityLogsReport.htm"


#set HTML style for results
$HTMLstyle = ""
$HTMLstyle = $HTMLstyle + "BODY{background-color:peachpuff;}"
$HTMLstyle = $HTMLstyle + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$HTMLstyle = $HTMLstyle + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
$HTMLstyle = $HTMLstyle + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
$HTMLstyle = $HTMLstyle + ""
$HTMLbodySYS = "System Log - Logon, Logoff, Lock and Unlock"
$HTMLbodySEC = "Security Log - UAC and logon"
$CSSStyle = @'
    
    ul {
     padding-left: 5px;
    }
    body { background-color:White;
    font-family:Tahoma;
     font-size:12pt;
    }
    td, th {border:1px solid black;} 
    th {
     color: black;
     background-color:peachpuff;
    }
    td { border-width: 1px;padding: 1px;border-style: solid;border-color: black; }
    TR:Hover TD { Background-Color: #C1D5F8; }
    table, tr, td, th { align:left; padding: 10px; margin: 0px; }
    table { width:75% }
    table { margin-left:0px; }
    
'@
$Head = $HTMLstyle + $CSSStyle


Write-Host "Processing... Please wait ..."


#pull lock and unlock from system log
$SYSevents  = Get-WinEvent -FilterHashtable @{ 
    Path		 = "$Drive\System.evtx"
    Id=@(7001,7002,20001,20003)
}
    #put numbers into meaningful words
    $type_lu = @{
        7001 = 'SYSTEMLOG   - User Logon'
        7002 = 'SYSTEMLOG   - User Logoff'
        4800 = 'SECURITYLOG - Lock'
        4801 = 'SECURITYLOG - UnLock'
        4688 = 'SECURITYLOG - USB Device Connected'
       20001 = 'SYSTEMLOG   - Device Installation'
       20003 = 'SYSTEMLOG   - Service Installation'
        7036 = 'SECURITYLOG - Service Control Manager Device Installation'
        4672 = 'SECURITYLOG - Special Privileges assigned to current user'
        4624 = 'SECURITYLOG - Account logged on'
    }
#pull lock and unlock from security log
$SECevents  = Get-WinEvent -FilterHashtable @{ 
    Path		 = "$Drive\Security.evtx"
    Id=@(7036,4672,4624,4688,4800,4801)
}


#xml paths
$ns = @{'ns'='http://schemas.microsoft.com/win/2004/08/events/event'}
$target_xpath = "//ns:Data[@Name='TargetUserName']"
$usersid_xpath = "//ns:Data[@Name='UserSid']"


#check if previous logfile exists
$SYStestexists = Test-Path $SYSresults
$SECtestexists = Test-Path $SECresults


#check if system log file exists and delete before running
    If ($SYStestexists -eq $True)
        { 
            Remove-Item $SYSresults
            Write-Host "Previous System logfile removed."
            
        } 
            else 
        {
            Write-Host "System logfile will be created as non exists."
        }
#check if security log file exists and delete before running
     If ($SECtestexists -eq $True)
        { 
            Remove-Item $SECresults
            Write-Host "Previous Security logfile removed."
            
        } 
            else 
        {
            Write-Host "Security logfile will be created as non exists."
        }


#pull data from xml for system log
If($SYSevents) {
    $XMLSYSresults = ForEach($eventSYS in $SYSevents) {
        $xmlSYS = $eventSYS.ToXml()
        Switch -Regex ($eventSYS.Id) {
            '4...' {
                $userSYS = (
                    Select-Xml -Content $xmlSYS -Namespace $ns -XPath $target_xpath
                ).Node.'#text'
                Break            
            }
            '7...' {
                $SYSsid = (
                    Select-Xml -Content $xmlSYS -Namespace $ns -XPath $usersid_xpath
                ).Node.'#text'
                #.translates needed to make usernames readable
                $userSYS = (
                    New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $SYSsid
                ).Translate([System.Security.Principal.NTAccount]).Value

                Break
            }
        }
        New-Object -TypeName PSObject -Property @{
            Time = $eventSYS.TimeCreated
            User = $userSYS
            Id   = $eventSYS.Id
            Type = $type_lu[$eventSYS.Id]
            
        }
    }

    #write the results pulled.
    If($XMLSYSresults) {
        #puts out results as a HTML file
        $XMLSYSresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySYS | Set-Content $SYSresults
        }
}


#pull data from xml for system log
If($SECevents) {
    $XMLSECresults = ForEach($eventSEC in $SECevents) {
        $xmlSEC = $eventSEC.ToXml()
        Switch -Regex ($eventSEC.Id) {
            '4...' {
                $userSEC = (
                    Select-Xml -Content $xmlSEC -Namespace $ns -XPath $target_xpath
                ).Node.'#text'
                Break            
            }
            '7...' {
                $SECsid = (
                    Select-Xml -Content $xmlSYS -Namespace $ns -XPath $usersid_xpath
                ).Node.'#text'
                #.translates needed to make usernames readable
                $userSEC = (
                    New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $SECsid
                ).Translate([System.Security.Principal.NTAccount]).Value
                Break
            }
        }
        New-Object -TypeName PSObject -Property @{
            Time = $eventSEC.TimeCreated
            User = $userSEC
            Id   = $eventSEC.Id
            Type = $type_lu[$eventSEC.Id]
            
        }
    }

    #write the results pulled.
    If($XMLSECresults) {
        #puts out results as a HTML file
        $XMLSECresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySEC | Set-Content $SECresults
        }
}


#success of fail test
$TestSYSresults = Test-Path $SYSresults
$TestSECresults = Test-Path $SECresults


#open html file if the system was successful
    If ($TestSYSresults -eq $True)
        { 
            Write-Host "System logfile Success."
            Invoke-Item $SYSresults
        } 
            else 
        {
            Write-Host "Error - System logfile Failed"
        }
#open html file if the security was successful
    If ($TestSECresults -eq $True)
        { 
            Write-Host "Security logfile Success."
            Invoke-Item $SECresults
        } 
            else 
        {
            Write-Host "Error - Security logfile Failed."
        }

This is working great on old log files from my computer. I’m able to see the user’s name and when they logged on and off.

But when I use an eventlog file from another computer it doesn’t pull the user’s name from the system.evtx file? I need ideas for resolutions? I’m considering that log is from an older windows version? or is it a permissions issue I’ve overlooked? Thanks for all your help.

I hate being “that guy”, but you have a typo in lines 152 and 163, it should read:

Write-Host "System logfile will be created as none exists."

Instead of:

Write-Host "System logfile will be created as non exists."

No problem at all, thank you for the correction :slight_smile:



#clear the screen
cls


#$Days = 1
$SECevents = @()


#get location of folder containing log files
Function Select-FolderDialog
{
    param([string]$Description="SELECT FOLDER CONTAINING SYSTEM.EVTX LOGFILE",[string]$RootFolder="MyComputer")

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
     Out-Null     

    $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
    $objForm.Rootfolder  = $RootFolder
    $objForm.Description = $Description
    $Show = $objForm.ShowDialog()
        If ($Show -eq "OK")
        {
            Return $objForm.SelectedPath
        }
        Else
        {
            Write-Error "Operation cancelled by user."
        }
    
}
$Drive = Select-FolderDialog # the variable contains user folder selection



#Security Log save dialog
Function Get-SaveFileSEC
{
    param([string]$Description="SELECT FOLDER TO SAVE SECURITY REPORT",[string]$initialDirectorySEC="MyComputer")

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
    Out-Null

    $SaveFileDialogSEC = New-Object System.Windows.Forms.SaveFileDialog
    $SaveFileDialogSEC.initialDirectory = $initialDirectorySEC
    $SaveFileDialogSEC.filter = "HTML Files (*.htm)|*.htm"
    $SaveFileDialogSEC.ShowDialog() | Out-Null
    $SaveFileDialogSEC.filename #= "SecurityLogsReport"
} 
$SECresults = Get-SaveFileSYS # the variable contains save file location



#set HTML style for results
$HTMLstyle = ""
$HTMLstyle = $HTMLstyle + "BODY{background-color:peachpuff;}"
$HTMLstyle = $HTMLstyle + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$HTMLstyle = $HTMLstyle + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
$HTMLstyle = $HTMLstyle + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
$HTMLstyle = $HTMLstyle + ""
$HTMLbodySYS = "System Log - Logon, Logoff, Lock and Unlock"
$HTMLbodySEC = "Security Log - UAC and logon"
$CSSStyle = @'
    
    ul {
     padding-left: 5px;
    }
    body { background-color:White;
    font-family:Tahoma;
     font-size:12pt;
    }
    td, th {border:1px solid black;} 
    th {
     color: black;
     background-color:peachpuff;
    }
    td { border-width: 1px;padding: 1px;border-style: solid;border-color: black; }
    TR:Hover TD { Background-Color: #C1D5F8; }
    table, tr, td, th { align:left; padding: 10px; margin: 0px; }
    table { width:75% }
    table { margin-left:0px; }
    
'@
$Head = $HTMLstyle + $CSSStyle


Write-Host "Processing... Please wait ..."


#pull lock and unlock from security log
$SECevents  = Get-WinEvent -FilterHashtable @{ 
    Path		 = "$Drive\Security.evtx"
    Id=@(4624)
    #4672,4688,4800,4801,7036
}

    #put numbers into meaningful words
    $type_lu = @{
        7001 = 'Service Start Operations'
        7002 = 'Service Start Operations'
        4800 = 'The workstation was locked'
        4801 = 'The workstation was unlocked'
        4688 = 'A new process has been created'
       20001 = 'Device Installation'
       20003 = 'Service Installation'
        7036 = 'Basic Service Operations'
        4672 = 'Special privileges assigned to new logon'
        4624 = 'An account was successfully logged on'
    }



#xml paths
$ns = @{'ns'='http://schemas.microsoft.com/win/2004/08/events/event'}
$target_xpath = "//ns:Data[@Name='TargetUserName']"
$usersid_xpath = "//ns:Data[@Name='UserSid']"


#check if previous logfile exists
$SECtestexists = Test-Path $SECresults


#check if security log file exists and delete before running
     If ($SECtestexists -eq $True)
        { 
            Remove-Item $SECresults
            Write-Host "Previous Security logfile removed."
            
        } 
            else 
        {
            Write-Host "Security logfile will be created as none exists."
        }


#pull data from xml for security log
If($SECevents) {
    $XMLSECresults = ForEach($eventSEC in $SECevents) {
        $xmlSEC = $eventSEC.ToXml()
        Switch -Regex ($eventSEC.Id) {
            '4...' {
                $userSEC = (
                    Select-Xml -Content $xmlSEC -Namespace $ns -XPath $target_xpath
                ).Node.'#text'
                Break            
            }
            '7...' {
                $SECsid = (
                    Select-Xml -Content $xmlSEC -Namespace $ns -XPath $usersid_xpath
                ).Node.'#text'
                #.translates needed to make usernames readable
                $userSEC = (
                    New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $SECsid
                ).Translate([System.Security.Principal.NTAccount]).Value
                Break
            }
        }
        New-Object -TypeName PSObject -Property @{
            Time = $eventSEC.TimeCreated
            User = $userSEC
            Id   = $eventSEC.Id
            Type = $type_lu[$eventSEC.Id]
        }
    }

    #write the results pulled.
    If($XMLSECresults) {
        #puts out results as a HTML file
        $XMLSECresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySEC | Set-Content $SECresults
        }
}


#success of fail test
$TestSECresults = Test-Path $SECresults



#open html file if the security was successful
    If ($TestSECresults -eq $True)
        { 
            Write-Host "Security logfile Success."
            Invoke-Item $SECresults
        } 
            else 
        {
            Write-Host "Error - Security logfile Failed."
        }

This is my current version. What I’m trying to do now is filter the XML to only show certain ‘LogOn Types’. don’t want type 4 and type 5 included by the end.

I’ve used event viewer and got this XML filter but I can’t seem to work this in to my script. Would I filter the Select-XML and use a property? Help greatly appreciated

#filter the xml data

*[System[(EventID=4624)]] and *[EventData[Data[@Name=‘LogonType’] and (Data=2 or Data=3 or Data=7 or Data=8 or Data=9 or Data=10 or Data=11)]]