2 Easy Ways to Schedule Restart Notifications with Intune

In today’s fast-paced and technology-driven world, managing and securing devices within an organization can be a challenging task. One crucial aspect of this is ensuring that devices are regularly updated and restarted without causing major disruptions to workflow. This is where Microsoft Intune steps in as a game-changer.

Schedule Restart Notification with Intune

In this blog post, we will focus on a powerful feature that we can utilize using Intune: scheduling restart notifications. This functionality is not just about keeping devices up to date, but also about enhancing user experience and maintaining productivity by providing timely notifications for necessary restarts after updates. Whether you are an IT professional, a systems administrator, or simply interested in the intricacies of device management, this post will provide you with valuable insights on leveraging Intune to schedule restart notifications efficiently, ensuring seamless operations within your digital environment.

Prompting User for Restart using a scheduled task

In the first chapter of our exploration, we turn our attention to the practical steps involved in prompting users for a restart using a scheduled task. This procedure is pivotal in ensuring that updates are applied effectively, without hampering the user’s ongoing tasks or productivity. We’ll walk through the intricacies of creating and deploying a scheduled task within Intune.

This includes configuring the task to trigger a restart notification at a time that minimizes disruption, yet ensures compliance with your organization’s update policies. By mastering this technique, IT administrators can strike a delicate balance between maintaining up-to-date systems and respecting the user’s work schedule. This chapter not only provides step-by-step guidance but also highlights best practices and potential pitfalls to avoid, ensuring a smooth and user-friendly experience in managing device restarts.

The remediation script that checks if the scheduled task exists and creates it if not is presented below.

Detection Script

# PowerShell Script for Intune Detection of Scheduled Task

# Check and define log file path
$LogFilePath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\TaskDetectionLog.txt"
if (-not (Test-Path -Path $LogFilePath)) {
    Write-Host "Log file path does not exist. Checking C:\Temp..."
    $LogFilePath = "C:\Temp\TaskDetectionLog.txt"
    if (-not (Test-Path -Path "C:\Temp")) {
        Write-Host "C:\Temp does not exist. Creating..."
        New-Item -ItemType Directory -Path "C:\Temp" -ErrorAction Stop
    }

    if (-not (Test-Path -Path $LogFilePath)) {
        New-Item -ItemType File -Path $LogFilePath -ErrorAction Stop
    }
}

# Function to write to log file
function Write-Log {
    param ([string]$message)
    try {
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "$timestamp - $message" | Out-File -FilePath $LogFilePath -Append
        Write-Host "$timestamp - $message"
    } catch {
        Write-Host "Error writing to log: $_"
    }
}

# Write script start to log
Write-Log "Detection Script Started"

# Task name to check
$taskName = "CheckRestartNotification"

# Check if the scheduled task exists
try {
    $taskExists = Get-ScheduledTask -TaskName $taskName -ErrorAction Stop

    if ($taskExists) {
        Write-Log "Task '$taskName' found. No remediation required."
        exit 0 # Exit code 0 for success
    } else {
        Write-Log "Task '$taskName' not found. Remediation required."
        exit 1 # Exit code 1 for failure
    }
} catch {
    Write-Log "Error checking task: $_"
    exit 1 # Exit code 1 for failure
}

# Write script end to log
Write-Log "Detection Script Ended"

Initially, the script sets up a log file path, aiming to record its activities. It checks for the existence of this log file in a predetermined directory. If it doesn’t find the file, the script then attempts to create it in an alternative location, including making the directory if necessary.

A crucial part of the script is the Write-Log function, designed to facilitate easy logging of activities. This function not only records messages with timestamps in the log file but also displays them on the console, ensuring any errors in logging are caught and displayed. Upon execution, the script logs its start, enhancing trackability. It then defines the specific task it needs to check, named “CheckRestartNotification”.

The script’s main operation is to verify the presence of this scheduled task using the Get-ScheduledTask cmdlet. If the task exists, it logs that no further action is needed and exits with a success code. Conversely, if the task is absent, it indicates that remediation is necessary and exits with a failure code. The script is wrapped up with a log entry marking its completion.

This structured approach not only automates the task detection process but also ensures clarity and ease of troubleshooting through detailed logging, making it an effective tool for managing updates and restarts in an Intune-managed environment.

Remediation Script

# PowerShell Script to Schedule Restart Notification

# Add necessary Windows types for toast notifications
try {
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -TypeDefinition @"
        using System;
        using System.Runtime.InteropServices;

        public static class ToastNotificationManager {
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
        }
"@ -ErrorAction Stop
    Write-Host "Windows types added successfully."
} catch {
    Write-Host "Error adding Windows types: $_"
}

# Check and define log file path
$LogFilePath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\RestartNotificationLog.txt"
if (-not (Test-Path -Path $LogFilePath)) {
    Write-Host "Log file path does not exist. Checking C:\Temp..."
    $LogFilePath = "C:\Temp\RestartNotificationLog.txt"
    if (-not (Test-Path -Path "C:\Temp")) {
        Write-Host "C:\Temp does not exist. Creating..."
        New-Item -ItemType Directory -Path "C:\Temp" -ErrorAction Stop
    }
    if (-not (Test-Path -Path $LogFilePath)) {
        New-Item -ItemType File -Path $LogFilePath -ErrorAction Stop
    }
}

# Function to write to log file
function Write-Log {
    param ([string]$message)
    try {
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "$timestamp - $message" | Out-File -FilePath $LogFilePath -Append
        Write-Host "$timestamp - $message"
    } catch {
        Write-Host "Error writing to log: $_"
    }
}

# Write script start to log
Write-Log "Script Started"

# Function to show toast notification
function Show-ToastNotification {
    param ([string]$message)
    try {
        $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
        $notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
        $notifyIcon.Visible = $true
        $notifyIcon.ShowBalloonTip(10000, "Restart Reminder", $message, [System.Windows.Forms.ToolTipIcon]::Info)
        Write-Log "Toast notification shown."
    } catch {
        Write-Log "Error showing toast notification: $_"
    }
}

# Function to check last restart time and show notification if needed
function Check-And-Notify {
    try {
        $lastBootUpTime = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
        $currentTime = Get-Date
        $daysSinceRestart = ($currentTime - $lastBootUpTime).Days

        if ($daysSinceRestart -ge 14) {
            # Show toast notification
            $toastMessage = "You haven't performed a restart for $daysSinceRestart days. For better performance, please perform a restart as soon as possible"
            Show-ToastNotification -message $toastMessage

            # Log notification
            Write-Log "Notification displayed: $toastMessage"
        } else {
            Write-Log "No restart required. Days since last restart: $daysSinceRestart"
        }
    } catch {
        Write-Log "Error in Check-And-Notify: $_"
    }
}

# Function to register the scheduled task
function Register-ScheduledTask {
    try {
        $scriptBlock = {
            Add-Type -AssemblyName System.Windows.Forms
            Check-And-Notify
        }

        $encodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($scriptBlock))

        $action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "-encodedCommand $encodedCommand" -ErrorAction Stop
        $trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 2 -DaysOfWeek Monday -At 10am -ErrorAction Stop
        $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ErrorAction Stop

        # Register the task
        Register-ScheduledTask -TaskName "CheckRestartNotification" -Action $action -Trigger $trigger -Settings $settings -Description "Check and notify for system restart every 2 weeks" -ErrorAction Stop

        Write-Log "Scheduled task 'CheckRestartNotification' registered"
    } catch {
        Write-Log "Error registering scheduled task: $_"
    }
}

# Attempt to register the task
try {
    Register-ScheduledTask
} catch {
    Write-Log "Error encountered during task registration: $_"
}

# Write script end to log
Write-Log "Script Ended"

The script starts by adding necessary Windows types for toast notifications, which are small messages that appear on the desktop. It attempts to load the necessary assemblies and types, and logs the success or failure of this action.

Next, the script establishes a log file path to record its operations. It checks for the existence of the log file in a specified directory, and if not found, attempts to create it in an alternative location, including creating the directory itself if it doesn’t exist. A Write-Log function is defined to facilitate logging activities with timestamps, enhancing the script’s transparency.

The core functionality of the script includes a “Show-ToastNotification” function. This function displays a toast notification with a custom message, using standard Windows notification icons. It logs the action of showing the notification.

Another key feature is the “Check-And-Notify” function. It calculates the number of days since the last system restart and shows a toast notification if the system hasn’t been restarted for a specified period (14 days in this case). This function uses system information to determine the last boot time and logs either the display of a notification or that no restart is required.

The script then defines a Register-ScheduledTask function, which sets up a scheduled task to periodically execute the restart check and notification display. This function creates the task with specified triggers and settings, like frequency and conditions under which the task should run, and registers it in the system. It logs the success or failure of the task registration.

Finally, the script attempts to register this scheduled task and logs the end of its execution. This comprehensive script thus automates the process of reminding users to restart their systems for better performance, using Intune’s capabilities to manage and maintain device health efficiently.

Prompting User for Restart using a Remediations script

In the second chapter, we delve deeper into the functionalities of Intune by focusing on the use of remediation scripts to prompt users for a restart. This approach adds another layer of flexibility and efficiency to device management.

We will explore how to craft and implement a custom script that intelligently determines if a restart is necessary post-update, and then effectively communicates this to the user. This chapter is designed to guide you through the scripting process, highlighting key elements such as scripting language choice, logic implementation, and user interface considerations. The aim is to provide a seamless and minimally intrusive user experience, while ensuring compliance and security through timely restarts.

Detection Script

# Detection Script: Check if a full restart has occurred in the last 2 weeks

# Define log file path
$LogFilePath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\RestartDetectionLog.txt"
if (-not (Test-Path -Path $LogFilePath)) {
    if (-not (Test-Path -Path "C:\Temp")) {
        New-Item -ItemType Directory -Path "C:\Temp" -ErrorAction Stop
    }
    $LogFilePath = "C:\Temp\RestartDetectionLog.txt"
    if (-not (Test-Path -Path $LogFilePath)) {
        New-Item -ItemType File -Path $LogFilePath -ErrorAction Stop
    }
}

# Function to write to log file
function Write-Log {
    param ([string]$message)
    try {
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "$timestamp - $message" | Out-File -FilePath $LogFilePath -Append
        Write-Host "$timestamp - $message"
    } catch {
        Write-Host "Error writing to log: $_"
    }
}

# Write script start to log
Write-Log "Restart Detection Script Started"

# Check last restart time
try {
    $lastBootTime = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
    $currentTime = Get-Date
    $daysSinceRestart = ($currentTime - $lastBootTime).Days

    if ($daysSinceRestart -lt 14) {
        Write-Log "Device restarted within the last 2 weeks. Days since restart: $daysSinceRestart"
        exit 0 # No remediation needed
    } else {
        Write-Log "Device not restarted in the last 2 weeks. Remediation required."
        exit 1 # Remediation required
    }
} catch {
    Write-Log "Error during restart check: $_"
    exit 1 # Remediation required on error
}

# Write script end to log
Write-Log "Restart Detection Script Ended"

The script begins by defining a log file path where it will record its operations. If the designated log file path doesn’t exist, the script creates an alternative directory and log file in the C:\Temp location, ensuring there’s always a place to store its logs.

A key function within the script, Write-Log, is designed for logging activities. This function records messages along with a timestamp to the log file and also echoes these messages to the console. This dual logging approach enhances the script’s transparency and provides a clear audit trail.

The script’s main operation commences with logging its start. It then retrieves the last boot time of the system using the Get-CimInstance cmdlet. By comparing this last boot time with the current date, the script calculates the number of days since the last restart. If this duration is less than 14 days, it logs that the device has been restarted within this timeframe and exits with a success code (indicating no remediation is needed). However, if the system has not been restarted in the last two weeks, it logs that remediation is required and exits with a failure code.

In the event of an error during this check, the script is designed to catch it, log the error, and also exit with a failure code, signaling that remediation is necessary. Finally, the script logs its completion. This detection script is a vital tool in ensuring regular system restarts for maintained efficiency and security, particularly in environments managed via Intune, where keeping devices up-to-date and in good working order is essential.

Remediation Script

# Remediation Script: Show a toast notification to prompt a restart

# Define log file path
$LogFilePath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\RestartRemediationLog.txt"
if (-not (Test-Path -Path $LogFilePath)) {
    if (-not (Test-Path -Path "C:\Temp")) {
        New-Item -ItemType Directory -Path "C:\Temp" -ErrorAction Stop
    }
    $LogFilePath = "C:\Temp\RestartRemediationLog.txt"
    if (-not (Test-Path -Path $LogFilePath)) {
        New-Item -ItemType File -Path $LogFilePath -ErrorAction Stop
    }
}

# Function to write to log file
function Write-Log {
    param ([string]$message)
    try {
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "$timestamp - $message" | Out-File -FilePath $LogFilePath -Append
        Write-Host "$timestamp - $message"
    } catch {
        Write-Host "Error writing to log: $_"
    }
}

# Function to show toast notification
function Show-ToastNotification {
    param ([string]$message)
    try {
        $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
        $notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
        $notifyIcon.Visible = $true
        $notifyIcon.ShowBalloonTip(10000, "Restart Reminder", $message, [System.Windows.Forms.ToolTipIcon]::Info)
        Write-Log "Toast notification shown."
    } catch {
        Write-Log "Error showing toast notification: $_"
    }
}

# Write script start to log
Write-Log "Restart Remediation Script Started"

# Show notification
Show-ToastNotification -message "You have not restarted your device in the last 2 weeks. Please restart for better performance."

# Write script end to log
Write-Log "Restart Remediation Script Ended"

The script starts by defining a path for a log file where it will document its operations. If the designated path doesn’t exist, it takes steps to create an alternative path and log file in C:\Temp, ensuring there’s a record of its activities.

A significant part of the script is the Write-Log function. This function is responsible for logging activities, capturing both the timestamp and the message, and outputting this information to the log file and the console. This dual approach to logging enhances the script’s transparency and provides a clear record of its actions.

Another crucial component is the Show-ToastNotification function. This function generates a toast notification, which is a small popup message on the user’s desktop. The script uses this function to display a message reminding the user to restart their device for better performance. It logs the display of this notification to keep track of its user interactions.

Upon execution, the script logs its start, providing a clear indication of when the remediation process began. It then immediately calls the Show-ToastNotification function with a predefined message about the necessity of a restart for system performance. Following the display of this notification, the script logs its completion.

Overall, this script is an efficient way to ensure users are reminded to restart their systems regularly, which is crucial for maintaining optimal device performance, especially in Intune-managed IT environments. The script’s ability to log its actions and display notifications makes it a valuable tool in the arsenal of IT administrators looking to improve system health and compliance.

Final remarks 

As we already saw above, we can notify a user for a restart following various approaches. In any case a detection and remediation script should be created. We could define the wanted time period to check for the update, as well as the time interval to which the detection script is going to run. Following any of the above two methods, will help us keep our devices fresh and at the best performance.

References

Leave a Reply

Your email address will not be published. Required fields are marked *