Advertisement
Unusual_Culture_4722

Shutdown Scheduler with Windows Update–Style Toast & Tray Snooze Feature

Jun 13th, 2025
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 7.52 KB | Software | 0 0
  1. #================================================================================
  2. # Shutdown Scheduler with Windows Update–Style Toast & Tray Snooze Feature
  3. #
  4. #  - Cancels any pending shutdown/restart.
  5. #  - Schedules a new restart in 15 minutes (shutdown /r /t 900 /f /c "Scheduled by Admin").
  6. #  - Displays a Windows Update–style toast notification.
  7. #  - Creates a system tray icon with context menu options:
  8. #       • Snooze for 1 Hour (cancels the scheduled restart and schedules one in 3600 seconds).
  9. #       • Restart Now (cancels the scheduled restart and restarts immediately).
  10. #       • Dismiss (leaves the scheduled restart as-is).
  11. #  - The tray icon auto-exits after 60 seconds if no action is taken.
  12. #
  13. # Run in a standard account.
  14. #================================================================================
  15.  
  16. #----- Begin Windows Update–Style Toast Notification Setup -----
  17. If ($PSVersionTable.PSVersion.Major -lt 6)
  18. {
  19.     $null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
  20.     $null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
  21. }
  22. else
  23. {
  24.     # Ensure NuGet package provider is installed
  25.     if ($null -eq (Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue))
  26.     {
  27.         try { $null = Install-PackageProvider -Name NuGet -Force -Scope CurrentUser -ErrorAction Stop }
  28.         catch { throw $_.Exception.Message }
  29.     }
  30.     # Ensure Microsoft.Windows.SDK.NET.Ref package is installed
  31.     if ($null -eq (Get-Package -ProviderName NuGet -Name Microsoft.Windows.SDK.NET.Ref -AllVersions -ErrorAction SilentlyContinue))
  32.     {
  33.         try { $null = Install-Package -Name Microsoft.Windows.SDK.NET.Ref -ProviderName NuGet -Force -Scope CurrentUser -ErrorAction Stop }
  34.         catch { throw $_.Exception.Message }
  35.     }
  36.     # Retrieve the latest WinRT.Runtime.dll and Microsoft.Windows.SDK.NET.dll files
  37.     $WinRTRuntime = Get-ChildItem -Path "$env:LOCALAPPDATA\PackageManagement\NuGet\Packages\Microsoft.Windows.SDK.NET.Ref.*" -Filter "WinRT.Runtime.dll" -Recurse -ErrorAction SilentlyContinue |
  38.         Sort-Object -Property VersionInfo.FileVersion -Desc | Select -ExpandProperty FullName | Select -First 1
  39.     $WinSDKNet = Get-ChildItem -Path "$env:LOCALAPPDATA\PackageManagement\NuGet\Packages\Microsoft.Windows.SDK.NET.Ref.*" -Filter "Microsoft.Windows.SDK.NET.dll" -Recurse -ErrorAction SilentlyContinue |
  40.         Sort-Object -Property VersionInfo.FileVersion -Desc | Select -ExpandProperty FullName | Select -First 1
  41.     # Load the required DLLs
  42.     Add-Type -Path $WinRTRuntime -ErrorAction Stop
  43.     Add-Type -Path $WinSDKNet -ErrorAction Stop
  44. }
  45. #----- End Notification Setup -----
  46.  
  47. # Function to display a Windows Update–style toast notification.
  48. function Show-WindowsUpdateToast {
  49.     param (
  50.         [Parameter(Mandatory=$true)]
  51.         [string]$Title,
  52.         [Parameter(Mandatory=$true)]
  53.         [string]$SubtitleText
  54.     )
  55.  
  56.     $AudioSource = "ms-winsoundevent:Notification.Default"
  57.  
  58.     # Windows Update–style toast XML template
  59.     [xml]$ToastTemplate = @"
  60. <toast duration="long">
  61.    <visual>
  62.        <binding template="ToastGeneric">
  63.            <text>Windows Updates – you know you love 'em</text>
  64.            <group>
  65.                <subgroup>
  66.                    <text hint-style="title" hint-wrap="true">$Title</text>
  67.                </subgroup>
  68.            </group>
  69.            <group>
  70.                <subgroup>
  71.                    <text hint-style="subtitle" hint-wrap="true">$SubtitleText</text>
  72.                </subgroup>
  73.            </group>
  74.        </binding>
  75.    </visual>
  76.    <audio src="$AudioSource"/>
  77. </toast>
  78. "@
  79.  
  80.     try {
  81.         $ToastXml = New-Object -TypeName Windows.Data.Xml.Dom.XmlDocument
  82.         $ToastXml.LoadXml($ToastTemplate.OuterXml)
  83.         $App = "Windows.SystemToast.WindowsUpdate.MoNotification2"
  84.         [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($App).Show($ToastXml)
  85.     }
  86.     catch {
  87.         Write-Host "Toast notification failed: $($_.Exception.Message)"
  88.     }
  89. }
  90.  
  91. #----- Cancel any existing scheduled shutdown/restart -----
  92. $shutdownOutput = shutdown /a 2>&1
  93. if ($shutdownOutput -match "No shutdown was scheduled") {
  94.     $cancelMessage = "No scheduled shutdown/restart was found."
  95. } else {
  96.     $cancelMessage = "A scheduled shutdown/restart was detected and cancelled."
  97. }
  98. Write-Host $cancelMessage
  99. Show-WindowsUpdateToast -Title "Shutdown Scheduler" -SubtitleText $cancelMessage
  100.  
  101. #----- Schedule new restart in 15 minutes -----
  102. shutdown /r /t 900 /f /c "Scheduled by Admin"
  103. $scheduleMessage = "New restart scheduled in 15 minutes. Right-click tray icon for options."
  104. Write-Host $scheduleMessage
  105. Show-WindowsUpdateToast -Title "Shutdown Scheduler" -SubtitleText $scheduleMessage
  106.  
  107. #----- Create a system tray icon with snooze options -----
  108. Add-Type -AssemblyName System.Windows.Forms
  109. Add-Type -AssemblyName System.Drawing
  110.  
  111. # Create a NotifyIcon (tray icon)
  112. $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
  113. $notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
  114. $notifyIcon.Text = "Shutdown Scheduler"
  115. $notifyIcon.Visible = $true
  116.  
  117. # Create a context menu for the tray icon
  118. $contextMenu = New-Object System.Windows.Forms.ContextMenu
  119.  
  120. # Menu item: Snooze for 1 Hour
  121. $snoozeItem = New-Object System.Windows.Forms.MenuItem "Snooze for 1 Hour"
  122. $snoozeItem.add_Click({
  123.     # Cancel existing scheduled shutdown and schedule restart in 1 hour
  124.     shutdown /a 2>&1 | Out-Null
  125.     shutdown /r /t 3600 /f /c "Snoozed by Admin"
  126.     [System.Windows.Forms.MessageBox]::Show("System snoozed for 1 hour.", "Shutdown Scheduler")
  127.     Show-WindowsUpdateToast -Title "Shutdown Scheduler" -SubtitleText "System snoozed for 1 hour."
  128.     $notifyIcon.Visible = $false
  129.     $notifyIcon.Dispose()
  130.     [System.Windows.Forms.Application]::Exit()
  131. })
  132.  
  133. # Menu item: Restart Now
  134. $restartNowItem = New-Object System.Windows.Forms.MenuItem "Restart Now"
  135. $restartNowItem.add_Click({
  136.     shutdown /a 2>&1 | Out-Null
  137.     shutdown /r /t 0 /f /c "Restart Now by Admin"
  138.     [System.Windows.Forms.MessageBox]::Show("System is restarting now.", "Shutdown Scheduler")
  139.     Show-WindowsUpdateToast -Title "Shutdown Scheduler" -SubtitleText "System is restarting now."
  140.     $notifyIcon.Visible = $false
  141.     $notifyIcon.Dispose()
  142.     [System.Windows.Forms.Application]::Exit()
  143. })
  144.  
  145. # Menu item: Dismiss (do nothing; keep current schedule)
  146. $dismissItem = New-Object System.Windows.Forms.MenuItem "Dismiss"
  147. $dismissItem.add_Click({
  148.     $notifyIcon.Visible = $false
  149.     $notifyIcon.Dispose()
  150.     [System.Windows.Forms.Application]::Exit()
  151. })
  152.  
  153. # Add items to the context menu
  154. $contextMenu.MenuItems.Add($snoozeItem)
  155. $contextMenu.MenuItems.Add($restartNowItem)
  156. $contextMenu.MenuItems.Add($dismissItem)
  157. $notifyIcon.ContextMenu = $contextMenu
  158.  
  159. # Optionally, show a balloon tip (for 5 seconds) to instruct the user
  160. $notifyIcon.ShowBalloonTip(5000, "Shutdown Scheduler", "Right-click the tray icon to Snooze for 1 Hour or Restart Now.", [System.Windows.Forms.ToolTipIcon]::Info)
  161.  
  162. #----- Set up a timer to auto-exit the tray icon after 60 seconds if no action is taken -----
  163. $timer = New-Object System.Windows.Forms.Timer
  164. $timer.Interval = 60000  # 60 seconds
  165. $timer.add_Tick({
  166.     $timer.Stop()
  167.     $notifyIcon.Visible = $false
  168.     $notifyIcon.Dispose()
  169.     [System.Windows.Forms.Application]::Exit()
  170. })
  171. $timer.Start()
  172.  
  173. # Run the Windows Forms message loop to keep the tray icon active
  174. [System.Windows.Forms.Application]::Run()
  175.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement