You can accomplish this easily with Intune's new "Detection and Remediation". You have two scripts, one to detect the last reboot and one to reboot the device.
I haven't checked this thoroughly, this is what ChatGPT came up with. Should be pretty close though.
Detect.ps1
<#
.SYNOPSIS
Exits 1 if last reboot is >= 7 days ago, else 0.
Compatible with Windows PowerShell 5.x (ships with Windows 10/11).
.NOTES
Good for Intune Proactive Remediations as a "detection" script.
#>
Threshold (in days)
$ThresholdDays = 7
try {
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$lastBoot = $os.LastBootUpTime
$uptime = (Get-Date) - $lastBoot
$msg = "Last reboot: {0} (uptime: {1:N1} days). Threshold: {2} days." -f $lastBoot, $uptime.TotalDays, $ThresholdDays
Write-Output $msg
if ($uptime.TotalDays -ge $ThresholdDays) {
# Too old -> signal remediation needed
exit 1
} else {
exit 0
}
}
catch {
Write-Error "Failed to determine last reboot time: $($_.Exception.Message)"
# On error, be conservative and signal remediation needed.
exit 1
}
Remediate.ps1
<#
.SYNOPSIS
Notifies the signed-in user(s) and schedules a reboot in 15 minutes.
Uses built-in tools: MSG.EXE and SHUTDOWN.EXE (no extra modules).
Users can temporarily cancel with: shutdown /a
.PARAMETER Minutes
Delay before reboot (default 15).
.PARAMETER BroadcastSeconds
Lifetime of the popup (default 60 seconds).
.NOTES
- Works on Windows 10/11 with Windows PowerShell 5.x.
- Requires the ability to restart the device (standard users typically can).
- The shutdown banner will also appear with a countdown.
#>
param(
[int]$Minutes = 15,
[int]$BroadcastSeconds = 60
)
Compute delay in seconds and ETA
$seconds = [Math]::Max(60, $Minutes * 60) # at least a minute for sanity
$eta = (Get-Date).AddSeconds($seconds).ToString("yyyy-MM-dd HH:mm:ss")
Compose a concise, user-facing message
$message = @"
Your computer will automatically restart in $Minutes minute(s) (at $eta).
Please save your work now.
To postpone temporarily, open Command Prompt and run: shutdown /a
(IT may reschedule the reboot later.)
"@
try {
# Best-effort popup to all local sessions (may no-op on some service contexts)
# /time controls how long the popup stays on screen before auto-closing
try {
& msg.exe * /time:$BroadcastSeconds $message | Out-Null
} catch {
# Ignore if MSG can't deliver (e.g., session isolation); SHUTDOWN will still show a system notification.
}
# Schedule the reboot with an official Windows countdown + notification
$shutdownComment = "IT notice: automatic restart in $Minutes minute(s). Save work now. Use 'shutdown /a' to cancel temporarily."
& shutdown.exe /r /t $seconds /c $shutdownComment /d p:0:0
Write-Output "Reboot scheduled in $Minutes minute(s) (ETA $eta). A system shutdown notification has been displayed."
Write-Output "To cancel temporarily: shutdown /a"
}
catch {
Write-Error "Failed to schedule reboot: $($_.Exception.Message)"
exit 1
}