Skip to main content

Worklet - Enforced Reboots with Notifications using Scheduled Tasks

  • May 10, 2021
  • 1 reply
  • 907 views

jack.smith
Forum|alt.badge.img+1

The idea behind this worklet is to display balloon tip in the taskbar once every 5 hours and then every 15 minutes to warn end users of an upcoming reboot and when.


If an end user reboots during the notification stages, there is a scheduled task that triggers upon restart that will run another powershell script that was written to cancel out running any future events built by this worklet.


The notification is using a custom icon file I built using a company logo.


Please do a lot of testing beforehand as the code is not professionally written to accommodate for every scenario one could encounter. Enjoy!


Evaluation Code


# Cleanup prior reboot task

Unregister-ScheduledTask -TaskName 'RebootMsg*' -Confirm:$false | Out-Null



# Establish Reboot Data Points

$uptime = (get-date) - (gcim Win32_OperatingSystem).LastBootUpTime

$sysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"



if($sysInfo.RebootRequired -or $uptime.Days -gt 28)

    { 

    exit 1}

else

    {

    exit 0}


Remediation Code


Unregister-ScheduledTask -TaskName 'RebootMsg*' -Confirm:$false | Out-Null



# Establish Reboot Data Points

$uptime = (get-date) - (gcim Win32_OperatingSystem).LastBootUpTime

$sysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"



if($sysInfo.RebootRequired -or $uptime.Days -gt 28)

{



# Balloon tip pop-up

$title = 'Company'

$icon = 'C:\Users\Public\Pictures\Company.ico'

$date = Get-Date ([datetime]::Now.AddMinutes(360)) -Format 'h:mm tt'

$msg = "As part of keeping Company safe, please save your work and reboot your computer. Automatic reboot at $date"

IF(!(Test-Path $icon)){Copy-Item Company.ico $icon | Out-Null}

$workdir = "C:\ProgramData\amagent"

IF(!(Test-Path $workdir)){mkdir $workdir | Out-Null}



# Cleanup Prior Scheduled tasks if they exist

Unregister-ScheduledTask -TaskName 'RebootMsg*' -Confirm:$false | Out-Null



function Build-Scripts{

# Build script that will send message

$vbs = @"

command = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -windowstyle hidden -File C:\ProgramData\Amagent\message.ps1 -Force"

 set shell = CreateObject("WScript.Shell")

 shell.Run command,0

"@

New-Item -Path "$workdir" -Name "message.vbs" -ItemType "file" -Value $vbs -force | Out-Null



$script = @"

`$BalloonTipText = ("$msg")

`$BalloonTipTitle = "$title"

`$BalloonTipTime = 1000

`$BalloonTipIcon = 'None'



Add-Type -AssemblyName System.Windows.Forms

Add-Type -AssemblyName System.Drawing

[Windows.Forms.ToolTipIcon]`$BalloonTipIcon = `$BalloonTipIcon

`$ContextMenu = New-Object System.Windows.Forms.ContextMenu

`$MenuItem = New-Object System.Windows.Forms.MenuItem

        

`$NotifyIcon = New-Object Windows.Forms.NotifyIcon -Property @{

    BalloonTipIcon = `$BalloonTipIcon

    BalloonTipText = `$BalloonTipText

    BalloonTipTitle = `$BalloonTipTitle

    ContextMenu = `$ContextMenu

    Icon = "C:\Users\Public\Pictures\Company.ico"

    Text = -join `$BalloonTipText[0..62]

    Visible = `$false

}

`$NotifyIcon.contextMenu.MenuItems.AddRange(`$MenuItem)

`$NotifyIcon.Visible = `$True

`$MenuItem.Text = "Exit"

`$MenuItem.add_Click({

    `$NotifyIcon.Visible = `$true

    `$NotifyIcon.ShowInTaskbar = `$true

})

`$NotifyIcon.ShowBalloonTip(`$BalloonTipTime)

"@

New-Item -Path "$workdir" -Name "message.ps1" -ItemType "file" -Value $script -force | Out-Null



$script = @"

# Cleanup Prior Scheduled tasks if they exist

Unregister-ScheduledTask -TaskName 'RebootMsg*' -Confirm:`$false

Remove-Item $workdir\message* -Confirm:`$false -Force

"@

New-Item -Path "C:\windows\temp\" -Name "message-stop.ps1" -ItemType "file" -Value $script -force | Out-Null



}

Build-Scripts



# Schedule actual Reboot

Function Schedule-Reboot{

    # This will create a scheduled task for SYSTEM REBOOT

    $TaskStartTime = [datetime]::Now.AddMinutes(360) # Six hours

    $SchedService = New-Object -ComObject Schedule.Service

    $SchedService.Connect()

    $Task = $SchedService.NewTask(0)

    $Task.RegistrationInfo.Description = 'Balloon tip pop-up'

    $Task.Settings.Enabled = $true

    $Task.Settings.AllowDemandStart = $true

    $trigger = $Task.triggers.Create(1) # https://docs.microsoft.com/en-us/windows/win32/taskschd/triggercollection-create

    $trigger.StartBoundary = $TaskStartTime.ToString("yyyy-MM-dd'T'HH🇲🇲ss")

    $trigger.Enabled = $true

    $action = $Task.Actions.Create(0)

    $action.Path = 'C:\Windows\System32\Shutdown.exe'

    $action.Arguments = "/r /t 900"

    $taskFolder = $SchedService.GetFolder('\')

    $taskFolder.RegisterTaskDefinition("RebootMsgReboot", $Task , 6, 'SYSTEM', $null, 4) | out-null

}

Schedule-Reboot



Function Stop-Reboot{

    # This will create a scheduled task for SYSTEM REBOOT

    $TaskStartTime = [datetime]::Now.AddMinutes(0) # Six hours

    $SchedService = New-Object -ComObject Schedule.Service

    $SchedService.Connect()

    $Task = $SchedService.NewTask(0)

    $Task.RegistrationInfo.Description = 'Balloon tip pop-up'

    $Task.Settings.Enabled = $true

    $Task.Settings.AllowDemandStart = $true

    $trigger = $Task.triggers.Create(8) # https://docs.microsoft.com/en-us/windows/win32/taskschd/triggercollection-create

    $trigger.StartBoundary = $TaskStartTime.ToString("yyyy-MM-dd'T'HH🇲🇲ss")

    $trigger.Enabled = $true

    $action = $Task.Actions.Create(0)

    $action.Path = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"

    $action.Arguments = "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File C:\windows\temp\message-stop.ps1 -Force"

    $taskFolder = $SchedService.GetFolder('\')

    $taskFolder.RegisterTaskDefinition("RebootMsgStop", $Task , 6, 'SYSTEM', $null, 4) | out-null

}

Stop-Reboot



# Sets up multiple scheduled tasks to run once every hour up to five hours, then every 15min there after

Function Schedule-RebootMsg {

    $i = 0 # Minutes

    $a = 0 # task count

    do

    {

       # This will create a scheduled task

        IF($i -ge 300){$i = $i + 15}else{$i = $i + 60}

        $TaskStartTime = [datetime]::Now.AddMinutes($i) # Now.AddMinutes(1)

        $SchedService = New-Object -ComObject Schedule.Service

        $SchedService.Connect()

        $Task = $SchedService.NewTask(0)

        $Task.RegistrationInfo.Description = 'Balloon tip pop-up'

        $Task.Settings.Enabled = $true

        $Task.Settings.AllowDemandStart = $true

        $trigger = $Task.triggers.Create(1) # https://docs.microsoft.com/en-us/windows/win32/taskschd/triggercollection-create

        $trigger.StartBoundary = $TaskStartTime.ToString("yyyy-MM-dd'T'HH🇲🇲ss")

        $trigger.Enabled = $true

        $action = $Task.Actions.Create(0)

        $action.Path = "$workdir\message.vbs"

        $taskFolder = $SchedService.GetFolder('\')

        $taskFolder.RegisterTaskDefinition("RebootMsg$a", $Task , 6, 'Users', $null, 4) | out-null

        $a++

    }

    while ($i -lt 360)

}

Schedule-RebootMsg



Start-ScheduledTask -TaskName RebootMsg0

Write-Output "Scheduled reboot for $date"

}else{ write-output "No Reboot Detected."}

1 reply

  • 0 replies
  • October 20, 2021

is there a similar worklet for macOS?


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings