AutomoxAutomox

Worklet: Predictable Reboot Notifications for Windows

AdamW-Automox
September 25, 2019 at 9:56 pm UTC

Hey Y’all!

Automox offers a fully customizable end-user notification feature that clearly indicates to users when Automox will be patching and potentially rebooting their systems. This feature also allows you to set custom deferral options empowering users to control when their device should be patched. This gives peace of mind to system admins that their environment will be patched without interfering with their users everyday use.

Although this is a great feature, Automox recognizes that it does not offer the predictability to users to when the actual reboot event will take place. We are currently working on improving our current notifications to give users better reboot predictability. Automox has gathered a lot of customer feedback aimed to make this feature enhancement as effective as possible. The great thing about this is it will be built into the product and be offered in the same fashion as the current end-user notifications.

So, what can you do until this feature is released? The majority of the feedback we received is that we are great about notifying the user to when patching begins, however, once patching is executed we do not let the user know exactly when the reboot will take place and allow them to defer the reboot.

This level of reboot predictability may not be a requirement for you. If it is? Worklets to the rescue!

The below Worklet will send end-user notifications to users through the form of Windows notifications. The notifications are fully customizable, these options include:

  • Custom notification messages for each notification
  • Frequency of notification messages sent
  • Custom reboot timing and notifying
  • Final reboot message forces user acknowledgement

Prerequisite:
The policy Reboot Notifications needs to be disabled. This is so the Worklet and policy end-user notifications do not conflict.

The Worklet remediation needs some customizing by the user. Each value needs to be set correctly in order for the notification messages to patch the timer values set, otherwise it may not reboot correctly.

There are a few values that you’ll need to set in the script. They are easily indicated with the “$” in front of each. Here is a list and what they do below. Pay attention to the naming, you’ll get a sense of how the Worklet will flow given each value you set. Also, if you need any assistance setting this up I would be happy to help, just reply to this post and I will be sure to help get this setup for you.

$rebootimer (ex: $rebootimer=5400) - This hardsets the time until the device reboots, in seconds.

$message1 (ex: $message1={your_message}) - Copy for the custom message in the first notification. Be sure to indicate the amount of time in minutes until the reboot. This was set previously in $rebootimer

$message2wait (ex: $message2wait=1800) - the amount of time elapsed until the second notification is sent, in seconds.

$message2 - Copy for the custom message in the second notification. Be sure to indicate the amount of time in minutes until the reboot. This was set previously in $rebootimer minus the time elapsed that was set in $message2wait. Indicate this in minutes (5400-1800=3600) which is 60 minutes.

$rebootimer2 (ex: $rebootimer=5400) - resets the reboot timer to the time indicated in the previous notification message ($message2). If you indicated 60 minutes, then set this time to 3600 seconds

And so on….

As you can see, you need to see the reboot time, the custom message, and the wait timer for the notification intervals. The logic needs to make sense when setting these so it flows with what the custom notification says and what the behavior of the reboot is. Below is the evaluation and remediation code for the Worklet. This will help you get a visual for one that is fully customized.

Evaluation:

10 lines
#exit 0 if no reboot is needed
#exit 1 if reboot is needed

$sysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"
if($sysInfo.RebootRequired)
    { 
    exit 1}
else
    {
    exit 0}

Remediation:

powershell47 lines
$sysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"
if($sysInfo.RebootRequired)
{
######################################################### Start Parameters - Editable #########################################################

#hardset the reboot countdown timer in seconds (e.g. 5400 for 90 minutes). After this time elapses reboot command is initiated. In this example it's 90 minutes
    $rebootimer = 5400
#set the first notification message copy. Include the reboot time value set previously. In this example it's 90 minutes
    $message1 = "Automox will automatically reboot your computer in 90 minutes. Please take time to save and close any open documents."
#Define the time to wait until the second notification message is sent in seconds (e.g. 1800 for 30 minutes). 
    $message2wait = 1800
#set the second notification message copy. In this example 60 minutes.   
    $message2 = "Automox will automatically reboot your computer in 60 minutes. Please take time to save and close any open documents."
#reset the reboot time to match the time indicated in the previous notification message copy (e.g. 3600 for 60 minutes)
    $rebootimer2 = 3600
#Define the time to wait for the third notification message to launch in seconds (e.g. 1800 for 30 minutes).  In this example it's 30 minutes 
    $message3wait = 1800
#set the third notification message copy.  In this example 30 minutes.
    $message3 = "Automox will automatically reboot your computer in 30 minutes. Please take time to save and close any open documents."
#reset the reboot time to match the time indicated in the previois notification message copy (e.g.1800 for 30 minutes)
    $rebootimer3 = 1800
#Define the time to wait for the final notification message to launch in seconds (e.g. 900 for 15 minutes). This needs to be in sync with when the reboot is scheduled. 
#In this example it will warn the users 15 minutes before the reboot, so we set it to 900 (15 minutes)
    $message4wait = 900
#set the final notification copy. The time for reboot should match the amount of time until the reboot take place
    $message4 = "Automox will automatically reboot your computer in 15 minutes. Please take time to save and close any open documents."
#reset the reboot time to match the time indicated in the previois notification message copy (e.g.300 for 15 minutes)
    $rebootimer4 = 900

################################################################ End Parameters ################################################################


### Commands being run ###
shutdown /a
shutdown /r /t $rebootimer /d p:4:1 /c $message1
Start-Sleep -Seconds $message2wait
shutdown /a
shutdown /r /t $rebootimer2 /d p:4:1 /c $message2
Start-Sleep -Seconds $message3wait
shutdown /a
shutdown /r /t $rebootimer3 /d p:4:1 /c $message3
Start-Sleep -Seconds $message4wait
shutdown /a
shutdown /r /t $rebootimer4 /d p:4:1 /c $message4
}
{
    exit 0}

In the above example, I am setting the reboot countdown at 90 minutes. It will then send 3 more notifications warning the user of the reboot within the 90 minute with.

  1. The first notification will be sent notifying the user that a reboot will occur in 90 minutes
    30 minutes elapses
  2. The second notification message is sent and notifies the user a reboot will occur in 60 minutes
    30 minutes elapses
  3. The third notification message is sent and notifies the user a reboot will occur in 30 minutes
    15 minutes elapses
  4. The forth notification message is sent and notifies the user a reboot will occur in 15 minutes

After that the user will get notified 2 more times automatically through Windows. This will force the user to confirm before they can keep using their desktop. This happens at 10 minutes and again at 5 minutes. Below is an example of what this looks like

After that, the system will reboot. This gives the user plenty of time to save off any work before the reboot occurs. Again, you can make this longer if you desire. I do recommend that is kept under 8 hours as the agent will remain scanning during this Worklet and will not run any further commands until the Worklet has finished.

Here is an example of what the normal windows notification looks like on the device in the Worklet example above:

That’s it! You are now all set the notify user before rebooting a device. If you need any assistance with setting this up please feel free to reach out to me!

This discussion is archived and closed to replies. Continue it in the Automox Community Slack.

Discuss on Slack

Replies (34)

ScottCookeSeptember 26, 2019
#1

I can’t wait to give this a spin this afternoon - thanks Adam!

AdamW-AutomoxSeptember 26, 2019
#2

You’re welcome! Please reach out if you have questions or need any assistance with setting it up.

owl-ITSeptember 26, 2019
#3

This looks great … will take for a spin today as well … users like to be informed.

Cheers!

AdamW-AutomoxSeptember 26, 2019
#4

Awesome! I agree, the more informed the better. Enjoy using this and let me know if you need any assistance!

jschafer5September 26, 2019
#5

We are a Mac heavy environment. While I love the concept of this (and it will certainly help our Windows devices), we are still needing options for our Mac users. Anything in the works?

AdamW-AutomoxSeptember 26, 2019
#6

Great question. I am currently looking into ways we could accomplish the same thing on Mac devices. Windows is straightforward since we just harness the built in Windows Notifications. I am not as rehearsed on what MacOS uses and how we could accomplish this.

I will update the community once I either have the Worklet created, or inform you that it’s not possible within the confines of a Worklet.

Thanks!

ScottCookeSeptember 26, 2019
#7

@awhitman

Adam,

Just finished my readthrough and am going to start testing. One thing that is not clear is whether this will work for both Windows 7 (which is EOL in January, yes, but there will still be devices that need to be patched up until the final patches) as well as Windows 10?

AdamW-AutomoxSeptember 26, 2019
#8

@ScottCooke

Hey Scott,

I did test this on a Windows 7 device and it worked the same as Windows 10, so it should work for all your Windows 7 devices. I would highly recommend running it on a single Windows 7 device first just to make sure it works as expected.

Thanks!

rlebOctober 16, 2019
#9

@awhitman If the user reboots before the timer is up. Does it clear the machines pending reboot status?

AdamW-AutomoxOctober 16, 2019
#10

Yes, if the user reboots their device before the Worklet does, then it will clear the reboot value (RebootRequired: True to RebootRequired: False), this is on the system. If you reboot the device from Automox, then we will clear the reboot flag in the console. However, if a user reboots it directly from the device, we will not clear the reboot flag in Automox until the device is rescanned by the agent, we do not rescan the device unless we perform the reboot.

As far as the reboot notification Worklet goes, if a user reboots their device early it will clear the reboot flag on the system which is what the Worklet keys off of to determine if a reboot is needed, and if so, to send the notifications. When the user reboots their device and the Worklet hasn’t finished running, then it will start the remediation code over from the beginning. This is why I added code at the beginning of the remediation script to re-evaluate the device to see if the reboot flag is “True” or “False”. If RebootRequired is True, then it sends the notifications and sets the reboot timer. If RebootRequired is False, then it exits “0” and doesn’t send notifications. If this logic wasn’t included then it would keep running the remediation code without checking the Reboot status and the user would get into a notification loop.

Hope this helps!

Nic-AutomoxNovember 18, 2019
#11

For those of you who are using this worklet, is it working well in your environment? Let us know here or in this topic:
 

 


For those of you who are using this Worklet:


Is it working well for you as a workaround for reboot notification issues? We’re trying to determine how well this is working for people so that we can prioritize a complete fix for the problem.

 

 

 

 

bfreyNovember 18, 2019
#12

I’ve had mixed results. It seems that having multiple updates that require reboots messes with it. I’ve had reports from users saying that they’ve seen the notification say 10 minutes until reboot and then another a couple minutes later pop-up saying 30 minutes until reboot, etc. I haven’t been able to replicate on my side to grab screenshots.

Also, some users have notifications disabled or set to quiet in Windows so they don’t see it.

Overall, it is working for the most part.

Nic-AutomoxNovember 18, 2019
#13

Thanks @bfrey! If you do get any any screen shots please send them on over to us.

jspitz12November 19, 2019
#14

I have also had mixed results with the reboot worklet. It seems to work the majority of the time, but our users don’t have the ability to say no or defer the reboot. I started looking into using this worklet with our environment because users would not get accurate time-of-reboot when their machine was to set to install and auto-reboot after patch (Some cases more than an hour after Automox message).

I don’t know if this is just a case of us having to change our patching policy around, and not give users the control. Would love to know if other Automox users have a similar case or how other people are doing it. I guess the big thing for us would be accurate alerting for reboot.

aescolasticoDecember 3, 2019
#15
1 line
osascript -e 'display notification "hello world!"'

Just a theory but this could allow you to execute these commands through a worklet. Not sure which option would work best (notification, alert, dialog) but you can play around with each.

TimL-AutomoxDecember 3, 2019
#16

@aescolastico great find, our hesitation with using osascript is that new privacy controls require the end user to “approve” the command when it’s invoked in macOS Catalina.

aescolasticoDecember 3, 2019
#17

Doh!
That is unfortunate.

Does running with sudo bypass that at all?

AdamW-AutomoxDecember 12, 2019
#18

I never tried the bypass option before, so not sure if it will work or not. Here is the Worklet bash code that @molly and I wrote for predictable reboot notifications using Mac. It works great locally on the device, however, it will not work using a Worklet because it utilities osascript. You could give it a try with the bypass option you mentioned to see if it will display the notifications on the Mac desktop.

Evaluation:

bash32 lines
softwareupdate -l > /tmp/output.txt & proccess_id=$!

        wait $process_id

grep -w "Tool" /tmp/output.txt > /dev/null

if [[ $? -eq 0 ]]; then

#shutdown -h +5

message1="Automox will reboot your system in 2 hours. Please take time to save and close any open documents."
osascript -e 'display notification "'"$message1"'"'

        sleep 10s

message2="Automox will reboot your system in 1 hour. Please take time to save and close any open documents."
osascript -e 'display notification "'"$message2"'"'

        sleep 10s

message3="Automox will reboot your system in 30 minutes. Please take time to save and close any open documents."
osascript -e 'display alert "'"$message3"'"'

        sleep 10s

message4="Automox will reboot your system in 10 minutes. Please take time to save and close any open documents."
osascript -e 'display alert "'"$message4"'"'


else 
        exit 1
fi
bsilberJune 15, 2020
#19

Is there a way to customize the font size? I have this deployed in my org and on newer machines with a 4K screen, the text is tiny - barely legible. Is there any option within the Worklet to set it at a specific size?

AdamW-AutomoxJune 15, 2020
#20

@bsilber

Unfortunately, there is no way to change the font that I am aware of. I will keep researching this more and let you know if I find anything.

Thanks

MaikelJuly 15, 2020
#21

Hi Guys i tried to change the results in the audit log so it won’t state exit 1 or exit 0 but what do i need to change in the code to get the following;

{
Write-Output “Reboot pending, starting reboot process”
exit 1}
else
{
Write-Output “No pending Reboot”
exit 0}

and for remediation

{
Write-Output “Reboot Initiated”
exit 0}

MaikelAugust 5, 2020
#22

Hi Guys,

i need your help i tried to move this to the next level to use baloons and the action center but the scripts run’s fine locally but the moment you put this in system context this never reaches the end-user.

can i pick your brains to see if we can make a workaround or something?

powershell90 lines
Function Show-BalloonTip {
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNull()]
        [String]
        $BalloonTipText,
        [Parameter(Position = 1)]
        [String]
        $BalloonTipTitle = 'Tip',
        [Parameter(Position = 2)]
        [ValidateSet('Error', 'Info', 'None', 'Warning')]
        [String]
        $BalloonTipIcon = 'None',
        [Parameter(Position = 3)]
        [Int]
        $BalloonTipTime = 1000
    )
    end {
        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 = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)
            Text = -join $BalloonTipText[0..62]
            Visible = $false
        }
        $NotifyIcon.contextMenu.MenuItems.AddRange($MenuItem)
        $NotifyIcon.Visible = $True
        $MenuItem.Text = "Exit"
        $MenuItem.add_Click({
           $NotifyIcon.Visible = $false
           $NotifyIcon.ShowInTaskbar = $false
        })
        $NotifyIcon.ShowBalloonTip($BalloonTipTime)     
        switch ($Host.Runspace.ApartmentState) {
            STA {
                $null = Register-ObjectEvent -InputObject $NotifyIcon -EventName BalloonTipClosed -Action {                     
                    $Sender.Dispose()
                    Unregister-Event $EventSubscriber.SourceIdentifier
                    Remove-Job $EventSubscriber.Action
                }
            }
            default {
                continue
            }
        }
    }
}

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

### Variables ###

#$wait30Minutes = 1800
#$wait15Minutes = 900
#$rebootTimer = 300

$wait30Minutes = 18
$wait15Minutes = 9
$rebootTimer = 3

$balloonTipIcon = "None"
$balloonTipTitle = "Your IT Department"

if($sysInfo)
#if($sysInfo.RebootRequired)
    {
    Show-BalloonTip -BalloonTipText "We have installed security updates. Your device will automatically reboot within 90 minutes. Please save your work." -BalloonTipTitle $balloonTipTitle -BalloonTipIcon $balloonTipIcon -BalloonTipTime 7500
    Start-Sleep -Seconds $wait30Minutes

    Show-BalloonTip -BalloonTipText "We have installed security updates. Your device will automatically reboot within 60 minutes. Please save your work." -BalloonTipTitle $balloonTipTitle -BalloonTipIcon $balloonTipIcon -BalloonTipTime 7500    
    Start-Sleep -Seconds $wait30Minutes

    Show-BalloonTip -BalloonTipText "We have installed security updates. Your device will automatically reboot within 30 minutes. Please save your work." -BalloonTipTitle $balloonTipTitle -BalloonTipIcon $balloonTipIcon -BalloonTipTime 7500
    Start-Sleep -Seconds $wait15Minutes

    Show-BalloonTip -BalloonTipText "We have installed security updates. Your device will automatically reboot within 15 minutes. Please save your work." -BalloonTipTitle $balloonTipTitle -BalloonTipIcon $balloonTipIcon -BalloonTipTime 15000
    Start-Sleep -Seconds 6

    ### Initate Reboot ###
    #shutdown /r /t $rebootTimer /d p:4:1
    Write-Output "System Rebooted!"
    }
Nic-AutomoxAugust 5, 2020
#23

The trick I’ve used to get messages to the end user involves running the script as a scheduled task as the currently logged in user. See this worklet for how that works:
 

 


This worklet uses msg.exe to send a notification to the currently logged in user. Once the user dismisses the notification message, a reboot command is immediately issued.
Things you can change in the script:

Edit the “Message to end user” to put in your custom message, such as “Click OK to reboot now”
The time to wait for the scheduled task. In this case we used 30 seconds but you might be able to get away with a shorter time window. In any case, this doesn’t matter to the end user, just …

 

 

 

 

MaikelAugust 5, 2020
#24

That’s a route i don’t want to go to, i will wait for the improved build-in version.

jesumyipAugust 15, 2020
#25

I have a custom script that does all that. A scheduled task also pops up a powershell window. I’ve also manage to make it hidden. The pop-up only appears if there is a user logged on.

The worket works great for me. The scheduled task does a pending-reboot check every hour and if there is one it will popup the balloon. You can configure the max number of popups per 24hours to avoid annoying the user. It also forces an auto reboot when it detects the computer is idle for a configurable amount of time within a particular time window of the day. So for example, idle detection returns true if computer is idle for 30minutes anywhere between 1am and 5am local time.

MaikelAugust 15, 2020
#26

Would you be willing to share this with us?

jesumyipAugust 17, 2020
#27

Here you go. Feel freer to reach out if you need help

.RebootNotifications.pdf (133.8 KB)

MaikelAugust 17, 2020
#28

impressive script, kudo’s! Just curious why base encode an image and not use another file attached to the worklet?

jesumyipAugust 17, 2020
#29

Just an old habit. 🙂 You can definitely use the method you mentioned - that’s probably easier 🙂

jesumyipOctober 7, 2020
#30

Hi everyone. I recently made a change to this worklet. It now installs 2 scheduled tasks.

Here is the new reboot powershell script:

powershell96 lines
Add-Type @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PInvoke.Win32 {

    public static class UserInput {

        [DllImport("user32.dll", SetLastError=false)]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        [StructLayout(LayoutKind.Sequential)]
        private struct LASTINPUTINFO {
            public uint cbSize;
            public int dwTime;
        }

        public static DateTime LastInput {
            get {
                DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
                DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
                return lastInput;
            }
        }

        public static TimeSpan IdleTime {
            get {
                return DateTime.UtcNow.Subtract(LastInput);
            }
        }

        public static int LastInputTicks {
            get {
                LASTINPUTINFO lii = new LASTINPUTINFO();
                lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
                GetLastInputInfo(ref lii);
                return lii.dwTime;
            }
        }
    }
}
'@

Function IsAutomaticReboot
{
    <# 
    
    Two conditions must be met for automatic reboot
    1. The local time must be between $rebootStartTime and $rebootEndTime
    2. There has not been any user input for at least $idleTime minutes

    #>

    $boolTimeConditionMet = $False
    $minTime = Get-Date $rebootStartTime
    $maxTime = Get-Date $rebootEndTime
    $now = Get-Date
    if ($minTime.TimeOfDay -le $now.TimeOfDay -and $maxTime.TimeOfDay -ge $now.TimeOfDay) 
    {
        $boolTimeConditionMet = $True
    }

    $boolIdleConditionMet = $False
    $idleTime = [PInvoke.Win32.UserInput]::IdleTime
    if ($idleTime.Minutes -ge $minIdleTime)
    {
        $boolIdleConditionMet = $True
    }

    return ($boolIdleConditionMet -and $boolTimeConditionMet)
}

Function RebootComputer
{
    Restart-Computer -Force
}

#---------------------------------------------------------------------------------------
# These parameters control the time of day window within which automatic reboot will be initiated
[string]$rebootStartTime = "1am"
[string]$rebootEndTime = "5am"

# If there is no user input detected for $minIdleTime minutes within $rebootStarTime and $rebootEndTime, automatic reboot
# will be initiated
[int]$minIdleTime = 30

# Check if a reboot is pending
$sysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"
if($sysInfo.RebootRequired)
{
  if (IsAutomaticReboot)
  {
    RebootComputer
  }
}

This scheduled job needs to be installed with certain properties for it to work. And here is the powershell script to do this:

powershell9 lines
$action = New-ScheduledTaskAction -Execute wscript.exe -Argument "//B C:\ProgramData\amagent\rebootNotification\Hidden.vbs C:\ProgramData\amagent\rebootNotification\RunToastHidden.cmd" 
$trigger = New-ScheduledTaskTrigger -Daily -At 9am
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -MultipleInstances Parallel
$task = Register-ScheduledTask -TaskName "Reboot No Reminder" -Trigger $trigger -Action $action -User "NT AUTHORITY\SYSTEM"
$task.Triggers.Repetition.Interval = "PT1H"
$task.Triggers.Repetition.Duration = "P1D"
$task.Settings.StartWhenAvailable = $True
$task | Set-ScheduledTask -ErrorAction SilentlyContinue
jesumyipOctober 7, 2020
#31

The reason for the change is this: the previous script would not reboot the computer between 1am and 5am if there is no user logged on.

imparted_logicMay 26, 2021
#32

would it be possible to share this in a non-PDF output?

GiveMeAMenAfterMidnightFebruary 8, 2023
#33

Maybe implement it directly in Automox ?

NvlddmkmNovember 15, 2023
#34

I think it would be helpful to include all dependencies, like this will require Toast notifications to be enabled or the user will never see these alerts (which is kinda a big deal).  You’d want to build some checks at the head of the script like the following, to a) check if notifications are enabled, and b) enable them.

powershell26 lines
function Test-WindowsPushNotificationsEnabled() {
    $ToastEnabledKey = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\PushNotifications" -Name ToastEnabled -ErrorAction Ignore).ToastEnabled
    if ($ToastEnabledKey -eq "1") {
        Write-Host "Toast notifications for the logged on user are enabled in Windows"
        $true
    }
    elseif ($ToastEnabledKey -eq "0") {
        Write-Host "Toast notifications for the logged on user are not enabled in Windows. The script will try to enable toast notifications for the logged on user"
        $false
    }
}

# Create Enable-WindowsPushNotifications
# This is used to re-enable toast notifications if the user disabled them generally in Windows
function Enable-WindowsPushNotifications() {
    $ToastEnabledKeyPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications"
    Write-Host "Trying to enable toast notifications for the logged on user"
    try {
        Set-ItemProperty -Path $ToastEnabledKeyPath -Name ToastEnabled -Value 1 -Force
        Get-Service -Name WpnUserService** | Restart-Service -Force
        Write-Host "Successfully enabled toast notifications for the logged on user"
    }
    catch {
        Write-Host "Failed to enable toast notifications for the logged on user. Toast notifications will probably not be displayed"
    }
}