<# .SYNOPSIS Shows when a computer shut down or restarted, who or what asked for it, and whether it was clean. .DESCRIPTION Reads the System event log with Get-WinEvent and returns one object per event: 1074 User32 A process or user asked for a shutdown or restart (with reason) 6006 EventLog The event log service stopped: a clean shutdown 6005 EventLog The event log service started: the machine booted 6008 EventLog The previous shutdown was unexpected 41 Microsoft-Windows-Kernel-Power The system rebooted without shutting down cleanly Works against remote computers over the Remote Event Log Management firewall rules. .PARAMETER ComputerName One or more computers. Defaults to this one. .PARAMETER Days How far back to look. Default: 7. .PARAMETER MaxEvents Cap on events per computer. Default: 500. .PARAMETER Credential Credentials for remote computers. .EXAMPLE .\Get-RebootHistory.ps1 -Days 30 .EXAMPLE .\Get-RebootHistory.ps1 -ComputerName PC-0142, SRV-APP01 | Where-Object Type -eq 'Unexpected' #> [CmdletBinding()] param( [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('CN', 'DNSHostName')] [string[]]$ComputerName = $env:COMPUTERNAME, [ValidateRange(1, 3650)][int]$Days = 7, [ValidateRange(1, 100000)][int]$MaxEvents = 500, [pscredential]$Credential ) begin { $filter = @{ LogName = 'System' ProviderName = 'User32', 'EventLog', 'Microsoft-Windows-Kernel-Power' Id = 1074, 6005, 6006, 6008, 41 StartTime = (Get-Date).AddDays(-$Days) } # The hashtable matches any provider with any ID, so double-check the pairs we actually want. $wanted = @{ 1074 = 'User32'; 6005 = 'EventLog'; 6006 = 'EventLog'; 6008 = 'EventLog'; 41 = 'Microsoft-Windows-Kernel-Power' } } process { foreach ($computer in $ComputerName) { $params = @{ FilterHashtable = $filter; MaxEvents = $MaxEvents; ErrorAction = 'Stop' } if ($computer -notin @('.', 'localhost', $env:COMPUTERNAME)) { $params.ComputerName = $computer } if ($Credential) { $params.Credential = $Credential } try { $events = Get-WinEvent @params } catch { if ($_.FullyQualifiedErrorId -like 'NoMatchingEventsFound*') { Write-Verbose "$computer : no shutdown or startup events in the last $Days day(s)" } else { Write-Warning "$computer : $($_.Exception.Message)" } continue } foreach ($e in $events) { if ($wanted[$e.Id] -ne $e.ProviderName) { continue } $type = $null; $user = $null; $process = $null; $reason = $null switch ($e.Id) { 1074 { # Properties: 0 process, 1 computer, 2 reason, 3 reason code, 4 shutdown type, 5 comment, 6 user $p = $e.Properties.Value $type = (Get-Culture).TextInfo.ToTitleCase([string]$p[4]) $process = ($p[0] -replace '\s*\(.*\)$', '') $reason = (@($p[2], $p[5]) | Where-Object { $_ }) -join ' | ' $user = $p[6] } 6005 { $type = 'Startup' } 6006 { $type = 'Clean shutdown' } 6008 { $type = 'Unexpected'; $reason = 'Previous shutdown was unexpected' } 41 { $type = 'Unexpected'; $reason = 'Kernel-Power 41: rebooted without a clean shutdown' } } [pscustomobject]@{ ComputerName = $e.MachineName TimeCreated = $e.TimeCreated EventId = $e.Id Type = $type User = $user Process = $process Reason = $reason } } } }