Getting the last reboot for a computer is easy and a common task in the administration of servers and workstations. It is a bit more complicated to get the reboot history. I use Get-WinEvent with the filterxml option. Below is the full text of the script, as WordPress has trouble with the text file. The ConvertTo-ISO8061Date function converts dates to the UTC in format required by XML query.
<# Get-RebootHistory.ps1 is a GUI script which reads a remote computer's event log for reboot events based on days selected by the user. Alan Kaplan, www.akaplan.com Public Verison 12/25/21 #> [CmdletBinding()] param ( #in multidomain environment, use FQDN, otherwise computer name ok [Parameter(Mandatory = $true)] [string] $ComputerFQDN ) Add-Type -Assembly PresentationFramework Add-Type -AssemblyName Microsoft.visualBasic Function ConvertTo-ISO8061Date ([string]$strDate) { #Get date as UTC in format required by query $u = [System.TimeZoneInfo]::ConvertTimeToUtc($strDate) #Reformat Get-Date $u -UFormat '+%Y-%m-%dT%H:%M:%S.000Z' } Function New-Trim([string]$strText) { #Remove returns $NoBreaks = '[^\x20-\x7E]' $strText = [regex]::Replace($strText, $NoBreaks, '') #Remove leading and trailing whitespace #https://www.regular-expressions.info/examples.html $trimRegEx = '^[ \t\s]+|[ \t\s]+$' [regex]::Replace($strText, $trimRegEx, '') } function Show-LargeDatePicker { $Today = (Get-Date).GetDateTimeFormats()[0] [xml]$DatePickerXAML = @" <Window x:Class="DatePicker.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DatePicker" x:Name="Window" Title="Choose Start and End Dates for Events" WindowStartupLocation = "CenterScreen" Width = "400" Height = "200" ShowInTaskbar = "False" ResizeMode="CanResizeWithGrip" WindowStyle="ToolWindow" Opacity="0.9"> <Window.Background> <LinearGradientBrush> <LinearGradientBrush.Transform> <ScaleTransform x:Name="Scaler" ScaleX="1" ScaleY="1"/> </LinearGradientBrush.Transform> <GradientStop Color="#CC064A82" Offset="1"/> <GradientStop Color="#FF6797BF" Offset="0.7"/> <GradientStop Color="#FF6797BF" Offset="0.3"/> <GradientStop Color="#FFD4DBE1" Offset="0"/> </LinearGradientBrush> </Window.Background> <Grid> <Grid.Resources> <Style x:Key="BigCal" TargetType="{x:Type Calendar}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Calendar}"> <Viewbox Height="300" Width="300"> <CalendarItem x:Name="PART_CalendarItem" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> </Viewbox> </ControlTemplate> </Setter.Value> </Setter> </Style> </Grid.Resources> <StackPanel Margin="2"> <Label>Start:</Label> <DatePicker x:Name="datePickerStart" CalendarStyle="{StaticResource BigCal}" /> <Label>End:</Label> <DatePicker x:Name="datePickerEnd" CalendarStyle="{StaticResource BigCal}" /> <StackPanel> <Button x:Name="btnOK" Content="OK" Margin="00,05,00,00" Width="50" Height="20"/> <Button x:Name="btnCancel" Content="Cancel" Margin="00,05,00,00" Width="50" Height="20"/> </StackPanel> </StackPanel> </Grid> </Window> "@ $DatePickerXAML.Window.RemoveAttribute("x:Class") $reader = (New-Object System.Xml.XmlNodeReader $DatePickerXAML) $DatePickerGui = [Windows.Markup.XamlReader]::Load( $reader ) $btnOK = $DatePickerGui.FindName("btnOK") $btnCancel = $DatePickerGui.FindName("btnCancel") $datePickerStart = $DatePickerGui.Findname("datePickerStart") $datePickerEnd = $DatePickerGui.Findname("datePickerEnd") $datePickerEnd.text = $today if ($Recover -eq $true) { $StartDate = (((Get-Date).AddDays(-60)).Date).GetDateTimeFormats()[0] $datePickerStart.text = $StartDate $DatePickerGui.Title = 'Click "OK" for 60 day search, the AD Recycle Bin max age' } $btnCancel.add_Click( { $DatePickerGui.Close() Stop-Process $PID }) $btnOK.add_Click( { $script:Start_Date = $datePickerStart.Text $script:End_Date = $datePickerEnd.Text $DatePickerGui.Close() }) [void] $DatePickerGui.ShowDialog() } Clear-Host Write-Host 'Choose start and end date of search in GUI, then click Ok' -ForegroundColor green Show-LargeDatePicker Clear-Host #Begin at midnight $Start = (Get-Date($Start_Date)).date $dtStart = ConvertTo-ISO8061Date -strdate $Start #End now if ((Get-Date $End_Date).Date -eq (Get-Date).date) { $End = Get-Date } Else { #End 1 ms before midnight $End = ((Get-Date($End_Date)).date).AddHours(24).AddMilliseconds(-1) } $dtEnd = ConvertTo-ISO8061Date -strDate $End $filterTemplate = @' <QueryList> <Query Id="0" Path="System"> <Select Path="System">*[System[(EventID=41 or EventID=1074 or EventID=1076) and TimeCreated[@SystemTime>='STARTDT' and @SystemTime<='ENDDT']]]</Select> </Query> </QueryList> '@ $XML = $filterTemplate.Replace('STARTDT', $dtStart).Replace('ENDDT', $dtEnd) Try { Write-Host "Getting events, please wait ... " -foreground green $events = Get-WinEvent -FilterXml $XML -ComputerName $ComputerFQDN -ErrorAction Stop Clear-Host @(Foreach ($event in $events) { # Convert the event to XML $eventXML = [xml]$Event.ToXml() # Iterate through each one of the XML message properties For ($i = 0; $i -lt $eventXML.Event.EventData.Data.Count; $i++) { # Append these as object properties $val = $eventXML.Event.EventData.Data[$i].'#text' $val = New-Trim $val Add-Member -InputObject $Event -MemberType NoteProperty -Force -Name $eventXML.Event.EventData.Data[$i].name -Value $val } $event }) | Select-Object TimeCreated, @{Name = "EventID"; Expression = { $_.ID } }, LevelDisplayName, @{Name = "User"; Expression = { $_.Param7 } }, ProviderName, RecordID, @{Name = "Shutdown Type"; Expression = { $_.Param5 } }, @{Name = "Message"; Expression = { ($_.message -split "`n")[0] } }, @{Name = "Process"; Expression = { $_.Param1 } } | Out-GridView -Title "Shutdown Event. Selected are sent to your clipboard as CSV" -PassThru | ConvertTo-Csv -NoTypeInformation | Set-Clipboard } Catch { [void][Microsoft.VisualBasic.Interaction]::MsgBox($error[0].Exception.Message, 'ApplicationModal,OkOnly,Critical', "Error querying $ComputerFQDN") }