Open hotzenwalder opened 1 year ago
Considering it's now October 10th, 2023 (more than 6 months since you opened this issue), I'd imagine you've either figured out how to fix the issue or have moved onto something else entirely. Regardless, I just came across this repository a few minutes ago and almost immediately noticed the same issue(s) you're describing.
I rewrote the entire PowerShell script but I'll just share the fix for the specific problem you asked for here:
$ProgressPreference = 'SilentlyContinue'
# Define how often you want your devices to be rebooted
$RebootDeadlineInDays = 7
# Retrieve the Operating System's "Uptime"
$Uptime = Get-ComputerInfo -Property OSUptime | Select-Object OSUptime
if ($Uptime.OSUptime.Days -ge $RebootDeadlineInDays) {
Write-Host "Operating System has been running for $($Uptime.OSUptime.Days) days! Reboot required."
Exit 0
} else {
Write-Host "Operating System was rebooted $($Uptime.OSUptime.Days) days ago! Compliance check: Pass."
Exit 1
}
Hope that helps! For what it's worth, you can choose to use different measurements of time ("Hours", "Minutes", etc.) by selecting the associated property in the "$Uptime" variable. For example, if you wanted to determine how many hours ago a device rebooted, you could use the following code:
$UptimeInDays = $Uptime.OSUptime.Days
$UptimeInHours = $Uptime.OSUptime.Hours
if ($UptimeInDays -eq 0) {
Write-Host "Device was rebooted $UptimeInHours hours ago!"
}
Thanks for the code, but I think this does not take Fast Boot into consideration. With the original script it detects my system was last booted this morning, but when I run your code it tells me my system was last rebooted 12 days ago, so be carefull when you use this code. I use a different code these days, but when I try to paste it here it becomes quite unreadable
Thanks for the code, but I think this does not take Fast Boot into consideration. With the original script it detects my system was last booted this morning, but when I run your code it tells me my system was last rebooted 12 days ago, so be carefull when you use this code. I use a different code these days, but when I try to paste it here it becomes quite unreadable
That's fair. I have Fast Startup disabled across all devices in our environment so that's a use-case I never would've come across.
Out of curiosity, what's your result when using the following?
$DeviceLastBootupTime = Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty LastBootupTime
$TimeDifference = (Get-Date) - $DeviceLastBootupTime
Write-Host "Device has been online for $($TimeDifference.Days) days, $($TimeDifference.Hours) hours and $($TimeDifference.Minutes) minutes."
*In all fairness*, however, technically your device hasn’t* rebooted in 12 days. With Fast Startup enabled, your device is simply going to sleep and waking up from hibernation.
The output is 'Device has been online for 13 days, 2 hours and 15 minutes.'. I know it technically has not rebooted since 13 days since it goes into hibernation, that's why we also disable fast boot so updates get installed properly.
Tried pasting my script again, but it won't get any better than this. Hope you can get the output from it you need with and without fast boot enabled
$Last_reboot = Get-ciminstance Win32_OperatingSystem | Select -Exp LastBootUpTime $Check_FastBoot = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power" -ea Silentlycontinue).HiberbootEnabled If(($Check_FastBoot -eq $null) -or ($Check_FastBoot -eq 0)){ $Boot_Event = Get-WinEvent -ProviderName "Microsoft-Windows-Kernel-Boot"| where {$_.ID -eq 27 -and $_.message -like "*0x0*"} If($Boot_Event -ne $null){ $Last_boot = $Boot_Event[0].TimeCreated } } ElseIf($Check_FastBoot -eq 1){ $Boot_Event = Get-WinEvent -ProviderName "Microsoft-Windows-Kernel-Boot"| where {$_.ID -eq 27 -and $_.message -like "*0x1*"} If($Boot_Event -ne $null){ $Last_boot = $Boot_Event[0].TimeCreated } } If($Last_boot -eq $null){ $Uptime = $Last_reboot }Else { If($Last_reboot -ge $Last_boot){ $Uptime = $Last_reboot }Else{ $Uptime = $Last_boot } } $Current_Date = get-date $Diff_boot_time = $Current_Date - $Uptime $Boot_Uptime_Days = $Diff_boot_time.Days $Hour = $Diff_boot_time.Hours $Minutes = $Diff_boot_time.Minutes $Reboot_Time = "$Boot_Uptime_Days day(s)" + ": $Hour hour(s)" + " : $minutes minute(s)" If($Boot_Uptime_Days -ge $Reboot_Delay){ write-host "$Reboot_Time" EXIT 1 }Else { write-output "No Reboot needed" EXIT 0 }
I was able to reformat your script to make it readable. The trick to posting any multi-line code is to use three of the backticks before your script and three more after it. You were only using 1 backtick which tells MarkDown that you're wanting to display inline code and not a block of code.
I appreciate you posting your script, though! I hope you don't mind, I've taken it and restructured it to better fit my use-case. I'm posting it here in case you (or anyone else) wants to take a look!
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'
Write-Host "[ Get-DeviceLastBootupTimeWithFastStartup.ps1 ]" -ForegroundColor Green
Write-Host "Determining whether Fast Startup is enabled, please wait... " -NoNewline
# Define Variables
$RebootThresholdInDays = 7
$FastStartupRegistryKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power"
$IsFastStartupEnabled = (Get-ItemProperty $FastStartupRegistryKeyPath -ErrorAction SilentlyContinue).HiberbootEnabled
Write-Host "Done!" -ForegroundColor Green
# Determine the last bootup time based on Fast Startup setting
$LastOSBootupTime = if ($IsFastStartupEnabled -eq 1) {
Write-Host "[Fast Startup] Enabled"
$LatestBootupEvent = Get-WinEvent -ProviderName "Microsoft-Windows-Kernel-Boot" | Where-Object { $_.ID -eq 27 -and $_.Message -like "*0x1*" }
$LatestBootupEvent[0].TimeCreated
}
elseif (($null -eq $IsFastStartupEnabled) -or ($IsFastStartupEnabled -eq 0)) {
Write-Host "[Fast Startup] Disabled"
(Get-CimInstance Win32_OperatingSystem).LastBootUpTime
}
else {
Write-Host "[WARNING] Unable to determine whether Fast Startup is enabled. Script exiting with exit code 1." -ForegroundColor Yellow
exit 1
}
# Calculate OS Uptime
if ($null -ne $LastOSBootupTime) {
Write-Host "[Last OS Bootup Time] $LastOSBootupTime"
$OsUptime = (Get-Date) - $LastOSBootupTime
$OsUptimeInDays = $OsUptime.Days
$OsUptimeInHours = $OsUptime.Hours
$OsUptimeInMinutes = $OsUptime.Minutes
Write-Host "[Operating System Uptime] $OsUptimeInDays day(s), $OsUptimeInHours hour(s), $OsUptimeInMinutes minute(s)"
# Check if reboot is needed
if ($OsUptimeInDays -ge $RebootThresholdInDays) {
Write-Host "Uptime threshold ($RebootThresholdInDays days) has been met or exceeded."
Write-Host "[Result] " -NoNewLine
Write-Host "Reboot required." -ForegroundColor Yellow
exit 2
}
else {
Write-Host "Uptime threshold ($RebootThresholdInDays days) has not been met."
Write-Host "[Result] " -NoNewline
Write-Host "No reboot required." -ForegroundColor Green
exit 0
}
}
else {
Write-Host "[WARNING] Unable to determine how long the Operating System has been running. Script exiting with exit code 1." -ForegroundColor Yellow
exit 1
}
Also, here's a screenshot of the output from the script above:
The script used to detect the last time a system was restarted gives an error on my Windows 10 build (19045.2728 Dutch) https://github.com/JayRHa/EndpointAnalyticsRemediationScripts/blob/main/Toast-RebootMessage/detect-reboot.ps1
The error is ` Cannot convert value "1680444208,84456" to type "System.Int32". Error: "De indeling van de invoertekenreeks is onjuist." At line:1 char:1
It's triggered by the command $diff = $now - $poweron, but the problem is probably related to the values of $now and $poweron. The returned values in the original script are
1680444208,84456
for $now and1680444197,71884
for $differ.If you replace the , with a . by changing the $now and $differ to these commands, it works.
$now = (Get-Date -UFormat "%s" -Date (Get-Date)) -replace (",",".")
$poweron = (Get-Date -UFormat "%s" -Date (Get-Process -Id $pid).StartTime) -replace (",",".")
New values are
1680444208.84456
for $now and1680444197.71884
for $differ and then the calculations work.I think it has something to do with the region we run in our enviroment Windows (Dutch), so the characters used for numbering might differ.