{"id":390389,"date":"2024-12-11T09:27:52","date_gmt":"2024-12-11T09:27:52","guid":{"rendered":"https:\/\/www.ninjaone.com\/?post_type=script_hub&#038;p=390389"},"modified":"2024-12-11T09:27:52","modified_gmt":"2024-12-11T09:27:52","slug":"notification-snooze-powershell","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/fr\/script-hub\/notification-snooze-powershell\/","title":{"rendered":"Comment envoyer une notification Snooze et Ignorer avec PowerShell"},"content":{"rendered":"<p>Une communication efficace est la cl\u00e9 de vo\u00fbte de la gestion informatique, en particulier dans les services g\u00e9r\u00e9s et les environnements d&rsquo;entreprise. Les notifications et les alertes jouent un r\u00f4le essentiel pour informer les \u00e9quipes et garantir la fiabilit\u00e9 du syst\u00e8me. Cet article de blog explore un script <a href=\"https:\/\/www.ninjaone.com\/it-hub\/endpoint-management\/what-is-powershell\/\">PowerShell<\/a> polyvalent qui permet aux professionnels de l&rsquo;informatique de cr\u00e9er et d&rsquo;envoyer des notifications toast avec des options personnalisables pour remettre \u00e0 plus tard ou ignorer (\u00ab\u00a0snooze and dismiss\u00a0\u00bb). Cette fonctionnalit\u00e9 de notification Snooze est particuli\u00e8rement utile pour les <a href=\"https:\/\/www.ninjaone.com\/fr\/quest-ce-quun-msp\">fournisseurs de services g\u00e9r\u00e9s (MSP)<\/a> et les \u00e9quipes informatiques qui recherchent des moyens l\u00e9gers et conviviaux de transmettre des messages critiques aux utilisateurs finaux.<\/p>\n<h2>Contexte<\/h2>\n<p>Dans Windows 10 et les versions ult\u00e9rieures, les notifications toast sont un moyen moderne d&rsquo;alerter les utilisateurs directement dans le syst\u00e8me d&rsquo;exploitation. Bien que des outils tiers puissent offrir des fonctionnalit\u00e9s similaires, ils s&rsquo;accompagnent souvent de co\u00fbts de licence, de frais g\u00e9n\u00e9raux inutiles ou d&rsquo;une personnalisation limit\u00e9e. Ce script PowerShell propose une alternative rationalis\u00e9e et rentable, permettant aux professionnels de l&rsquo;informatique de cr\u00e9er des notifications \u00ab\u00a0Snooze et Ignorer\u00a0\u00bb adapt\u00e9es \u00e0 des besoins sp\u00e9cifiques.<\/p>\n<p>Les MSP et les administrateurs informatiques b\u00e9n\u00e9ficient grandement de cet outil. Qu&rsquo;il s&rsquo;agisse de rappeler aux utilisateurs les mises \u00e0 jour en attente, de les informer des pannes critiques ou de fournir des informations sur l&rsquo;\u00e9tat du syst\u00e8me pendant sa maintenance, la capacit\u00e9 \u00e0 d\u00e9livrer des messages interactifs am\u00e9liore directement l&rsquo;efficacit\u00e9 op\u00e9rationnelle et l&rsquo;engagement des utilisateurs.<\/p>\n<h2>Le script\u00a0:<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 5.1\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Sends a toast snooze\/dismiss notification to the currently signed in user. Please run as the Current Logged-on User. The script defaults to using NinjaOne's logo if none is provided.\r\n.DESCRIPTION\r\n    Sends a toast snooze\/dismiss notification to the currently signed in user. Please run as 'Current Logged on User'.\r\n    This defaults to using NinjaOne's logo in the Toast Message, but you can specify any png formatted image from a url.\r\n    You can also specify the \"ApplicationId\" to any string. The default is \"NinjaOne RMM\".\r\n\r\n    By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n\r\n.EXAMPLE\r\n    -Title \"My Title Here\" -Message \"My Message Here\"\r\n    Sends the title \"My Title Here\" and message \"My Message Here\" as a Toast message\/notification to the currently signed in user.\r\n.EXAMPLE\r\n    -Title \"My Title Here\" -Message \"My Message Here\" -ApplicationId \"MyCompany\"\r\n    Sends the title \"My Title Here\" and message \"My Message Here\" as a Toast message\/notification to the currently signed in user.\r\n        ApplicationId: Creates a registry entry for your toasts called \"MyCompany\".\r\n        PathToImageFile: Downloads a png image for the icon in the toast message\/notification.\r\n        SnoozeTimeOptionsInMinutes: Adds a dropdown to the toast message\/notification with options for snoozing the message.\r\n.OUTPUTS\r\n    None\r\n.NOTES\r\n    If you want to change the defaults then with in the param block.\r\n    ImagePath uses C:\\Users\\Public\\ as that is accessible by all users.\r\n    If you want to customize the application name to show your company name,\r\n        then look for $ApplicationId and change the content between the double quotes.\r\n\r\n    Minimum OS Architecture Supported: Windows 10 (IoT editions are not supported due to lack of shell)\r\n    Release Notes: Renamed script, Updated Script Variables\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam\r\n(\r\n    [string]$Title,\r\n    [string]$Message,\r\n    [string]$ApplicationId,\r\n    [string]$SnoozeTimeOptionsInMinutes,\r\n    [string]$PathToImageFile\r\n)\r\n\r\nbegin {\r\n    $Base64 = 'iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAJFBMVEUARF0Apc0AmL8ApM0Aos0Aps7\/\/\/8Am8ia1ug9rtLd8\/jw+\/2tMDHwAAAABXRSTlMBrBTIcce4nvwAAAIeSURBVHic7dvrcoMgEAXgiOAivv\/7Fm+JBpCLwk7bsz86rcNkPw+Y0Gl5vd4lGtbLKSG7vmF18mwQnWpe3YcghP2Z1svU8OtbIOihm8op25M2gWBov9UqYJj\/vSRzAGsEkhMglxngWINbdbxLAAAAAAAAAAAAAKAI8Oz2KRtApPWThEyAbT8NZwDZGpeav6sLIKXNMBwAtuGotTGTvTpMRms9qkxEBsDe\/dz+A7B3rufeS\/utrCKPkAywzfYmK8BeOHY+lBkzBImALfwDgA4XnNLphCTA4e43AKmL9vNMJD8pCQAna20nP5D+SfkQgJyp1qS9PYsEKQDnpVP627WYJCgBmGj+GRmUAFIraSXWBAwDcwJJk1AXMIzcgHgElQHxCGoDohHcBsybgIvPpei70S2A0csuaNkTBRBTbA7uAOb271E0+gWxOSgHfG87yD+wGsCz7fGONNf9iwGTb89DnlkwkUVQCPD2t1sXz9A6gMDT5YsgsggKARljI\/vTMkDo7cU3B1USCL+oOwdVAMGF5RlcAxB+tBoBwq\/JDlDcAPYEAGgDuPiNBwkgASSABJAAEkACSAAJIAEkgASQABL4JwlcA9w\/9N4GTOZcl1OQMTgRoEannhv9O\/+PCAAAAAAAAAAAAACAPwhgP+7HeOCR1jOfjBHI9dBrz9W\/34\/d9jyHLvvPweP2GdCx\/3zyvLlAfZ8+l13LktJzAJ+nfgAP50EVLvPsRgAAAABJRU5ErkJggg=='\r\n    [string]$ImagePath = \"$($env:SystemDrive)\\Users\\Public\\PowerShellToastSnoozeImage.png\"\r\n\r\n    # Set the default ApplicationId if it's not provided. Use the Company Name if available, otherwise use the default.\r\n    $ApplicationId = if ($env:NINJA_COMPANY_NAME) { $env:NINJA_COMPANY_NAME } else { \"NinjaOne RMM\" }\r\n\r\n    Write-Host \"[Info] Using ApplicationId: $($ApplicationId -replace '\\s+','.')\"\r\n\r\n    if ($env:title -and $env:title -notlike \"null\") { $Title = $env:title }\r\n    if ($env:message -and $env:message -notlike \"null\") { $Message = $env:message }\r\n    if ($env:applicationId -and $env:applicationId -notlike \"null\") { $ApplicationId = $env:applicationId }\r\n    if ($env:pathToImageFile -and $env:pathToImageFile -notlike \"null\") { $PathToImageFile = $env:pathToImageFile }\r\n    if ($env:snoozeTimeOptionsInMinutes -and $env:snoozeTimeOptionsInMinutes -notlike \"null\") { $SnoozeTimeOptionsInMinutes = $env:snoozeTimeOptionsInMinutes }\r\n\r\n    if ([String]::IsNullOrWhiteSpace($Title)) {\r\n        Write-Host \"[Error] A Title is required.\"\r\n        exit 1\r\n    }\r\n    if ([String]::IsNullOrWhiteSpace($Message)) {\r\n        Write-Host \"[Error] A Message is required.\"\r\n        exit 1\r\n    }\r\n\r\n    if ($Title.Length -gt 82) {\r\n        Write-Host \"[Warn] The Title is longer than 82 characters. The title will be truncated by the Windows API to 82 characters.\"\r\n    }\r\n    if ($Message.Length -gt 160) {\r\n        Write-Host \"[Warn] The Message is longer than 160 characters. The message might get truncated by the Windows API.\"\r\n    }\r\n\r\n    function Test-IsSystem {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        return $id.Name -like \"NT AUTHORITY*\" -or $id.IsSystem\r\n    }\r\n\r\n    if (Test-IsSystem) {\r\n        Write-Host \"[Error] Please run this script as 'Current Logged on User'.\"\r\n        Exit 1\r\n    }\r\n\r\n    function Set-RegKey {\r\n        param (\r\n            $Path,\r\n            $Name,\r\n            $Value,\r\n            [ValidateSet(\"DWord\", \"QWord\", \"String\", \"ExpandedString\", \"Binary\", \"MultiString\", \"Unknown\")]\r\n            $PropertyType = \"DWord\"\r\n        )\r\n        if (-not $(Test-Path -Path $Path)) {\r\n            # Check if path does not exist and create the path\r\n            New-Item -Path $Path -Force | Out-Null\r\n        }\r\n        if ((Get-ItemProperty -Path $Path -Name $Name -ErrorAction Ignore)) {\r\n            # Update property and print out what it was changed from and changed to\r\n            $CurrentValue = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction Ignore).$Name\r\n            try {\r\n                Set-ItemProperty -Path $Path -Name $Name -Value $Value -Force -Confirm:$false -ErrorAction Stop | Out-Null\r\n            }\r\n            catch {\r\n                Write-Host \"[Error] Unable to Set registry key for $Name please see below error!\"\r\n                Write-Host $_.Exception.Message\r\n                exit 1\r\n            }\r\n            Write-Host \"[Info] $Path\\$Name changed from:\"\r\n            Write-Host \" $CurrentValue to:\"\r\n            Write-Host \" $($(Get-ItemProperty -Path $Path -Name $Name -ErrorAction Ignore).$Name)\"\r\n        }\r\n        else {\r\n            # Create property with value\r\n            try {\r\n                New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType $PropertyType -Force -Confirm:$false -ErrorAction Stop | Out-Null\r\n            }\r\n            catch {\r\n                Write-Host \"[Error] Unable to Set registry key for $Name please see below error!\"\r\n                Write-Host $_.Exception.Message\r\n                exit 1\r\n            }\r\n            Write-Host \"[Info] Set $Path\\$Name to:\"\r\n            Write-Host \" $($(Get-ItemProperty -Path $Path -Name $Name -ErrorAction Ignore).$Name)\"\r\n        }\r\n    }\r\n\r\n    function ConvertFrom-Base64 {\r\n        param(\r\n            $Base64,\r\n            $Path\r\n        )\r\n        $bytes = [Convert]::FromBase64String($Base64)\r\n\r\n        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue\r\n        [IO.File]::WriteAllBytes($Path, $bytes)\r\n        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Continue\r\n    }\r\n\r\n    # Utility function for downloading files.\r\n    function Invoke-Download {\r\n        param(\r\n            [Parameter()]\r\n            [String]$URL,\r\n            [Parameter()]\r\n            [String]$Path,\r\n            [Parameter()]\r\n            [int]$Attempts = 3,\r\n            [Parameter()]\r\n            [Switch]$SkipSleep\r\n        )\r\n        Write-Host \"[Info] Used $PathToImageFile for the image and saving to $ImagePath\"\r\n\r\n        $SupportedTLSversions = [enum]::GetValues('Net.SecurityProtocolType')\r\n        if ( ($SupportedTLSversions -contains 'Tls13') -and ($SupportedTLSversions -contains 'Tls12') ) {\r\n            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol::Tls13 -bor [System.Net.SecurityProtocolType]::Tls12\r\n        }\r\n        elseif ( $SupportedTLSversions -contains 'Tls12' ) {\r\n            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12\r\n        }\r\n        else {\r\n            # Not everything requires TLS 1.2, but we'll try anyways.\r\n            Write-Host \"[Warn] TLS 1.2 and or TLS 1.3 isn't supported on this system. This download may fail!\"\r\n            if ($PSVersionTable.PSVersion.Major -lt 3) {\r\n                Write-Host \"[Warn] PowerShell 2 \/ .NET 2.0 doesn't support TLS 1.2.\"\r\n            }\r\n        }\r\n\r\n        $i = 1\r\n        While ($i -le $Attempts) {\r\n            # Some cloud services have rate-limiting\r\n            if (-not ($SkipSleep)) {\r\n                $SleepTime = Get-Random -Minimum 1 -Maximum 7\r\n                Write-Host \"[Info] Waiting for $SleepTime seconds.\"\r\n                Start-Sleep -Seconds $SleepTime\r\n            }\r\n            if ($i -ne 1) { Write-Host \"\" }\r\n            Write-Host \"[Info] Download Attempt $i\"\r\n\r\n            $PreviousProgressPreference = $ProgressPreference\r\n            $ProgressPreference = 'SilentlyContinue'\r\n            try {\r\n                # Invoke-WebRequest is preferred because it supports links that redirect, e.g., https:\/\/t.ly\r\n                # Standard options\r\n                $WebRequestArgs = @{\r\n                    Uri                = $URL\r\n                    MaximumRedirection = 10\r\n                    UseBasicParsing    = $true\r\n                    OutFile            = $Path\r\n                }\r\n\r\n                # Download The File\r\n                Invoke-WebRequest @WebRequestArgs\r\n\r\n                $ProgressPreference = $PreviousProgressPreference\r\n                $File = Test-Path -Path $Path -ErrorAction SilentlyContinue\r\n            }\r\n            catch {\r\n                Write-Host \"[Error] An error has occurred while downloading!\"\r\n                Write-Warning $_.Exception.Message\r\n\r\n                if (Test-Path -Path $Path -ErrorAction SilentlyContinue) {\r\n                    Remove-Item $Path -Force -Confirm:$false -ErrorAction SilentlyContinue\r\n                }\r\n\r\n                $File = $False\r\n            }\r\n\r\n            if ($File) {\r\n                $i = $Attempts\r\n            }\r\n            else {\r\n                Write-Host \"[Error] File failed to download.\"\r\n                Write-Host \"\"\r\n            }\r\n\r\n            $i++\r\n        }\r\n\r\n        if (-not (Test-Path $Path)) {\r\n            Write-Host \"[Error] Failed to download file!\"\r\n            exit 1\r\n        }\r\n        else {\r\n            return $Path\r\n        }\r\n    }\r\n\r\n    function Show-Notification {\r\n        [CmdletBinding()]\r\n        Param (\r\n            [string]\r\n            $ApplicationId,\r\n            [string]\r\n            $ToastTitle,\r\n            [string]\r\n            [Parameter(ValueFromPipeline)]\r\n            $ToastText,\r\n            [string]\r\n            $SnoozeOptions\r\n        )\r\n\r\n        # Import all the needed libraries\r\n        [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] &gt; $null\r\n        [Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] &gt; $null\r\n        [Windows.System.User, Windows.System, ContentType = WindowsRuntime] &gt; $null\r\n        [Windows.System.UserType, Windows.System, ContentType = WindowsRuntime] &gt; $null\r\n        [Windows.System.UserAuthenticationStatus, Windows.System, ContentType = WindowsRuntime] &gt; $null\r\n        [Windows.Storage.ApplicationData, Windows.Storage, ContentType = WindowsRuntime] &gt; $null\r\n\r\n        # Make sure that we can use the toast manager, also checks if the service is running and responding\r\n        try {\r\n            $ToastNotifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier(\"$ApplicationId\")\r\n        }\r\n        catch {\r\n            Write-Host $_.Exception.Message\r\n            Write-Host \"[Error] Failed to create notification.\"\r\n        }\r\n\r\n        # Create the xml for the snooze options\r\n        $IsFirst = $true\r\n        if ($($SnoozeOptions -split ',').Count -gt 5) {\r\n            Write-Host \"[Error] Too many snooze options provided. Maximum is 5.\"\r\n            exit 1\r\n        }\r\n        $SnoozeXml = $SnoozeOptions -split ',' | ForEach-Object {\r\n            # Trim whitespace\r\n            $Option = \"$_\".Trim()\r\n            if ($IsFirst) {\r\n                # Add the input and default selection\r\n                \"&lt;input id='snoozeTime' type='selection' defaultInput='$Option'&gt;\"\r\n                $IsFirst = $false\r\n            }\r\n            # Check if the option is a number\r\n            if ([int]::TryParse($Option, [ref]$null)) {\r\n                # Convert the number to an integer\r\n                $Option = [int]$Option\r\n            }\r\n            else {\r\n                # If not a number, exit with an error\r\n                Write-Host \"[Error] Invalid snooze time option '$Option' provided.\"\r\n                exit 1\r\n            }\r\n            # Add the selection\r\n            if ($Option -ge 60) {\r\n                # Get the number of hours and minutes\r\n                # Round the number of hours to the nearest hour\r\n                $Hours = [math]::Round($Option \/ 60, 0)\r\n                # Get the number of minutes\r\n                $MinutesMod = $Option % 60\r\n                # Format the number of minutes\r\n                $Minutes = if ($MinutesMod -eq 0) {\r\n                    # If the number of minutes is 0, don't display anything\r\n                    \"\"\r\n                }\r\n                elseif ($MinutesMod -gt 1) {\r\n                    # If the number of minutes is greater than 1, format it as ' 2 Minutes'\r\n                    \" $MinutesMod Minutes\"\r\n                }\r\n                elseif ($MinutesMod -eq 1) {\r\n                    # If the number of minutes is 1, format it as ' 1 Minute'\r\n                    \" $MinutesMod Minute\"\r\n                }\r\n                # Format the number of hours\r\n                $Unit = if ($Hours -gt 1) { 'Hours' }else { 'Hour' }\r\n                \"&lt;selection id='$($Option)' content='$($Hours) $($Unit)$($Minutes)'\/&gt;\"\r\n            }\r\n            elseif ($Option -lt 60) {\r\n                # Format the number of minutes when it's less than 60 minutes\r\n                $Minutes = $Option\r\n                $Unit = if ($Minutes -gt 1) { 'Minutes' }else { 'Minute' }\r\n                \"&lt;selection id='$($Option)' content='$($Minutes) $($Unit)'\/&gt;\"\r\n            }\r\n        }\r\n\r\n        # Create a new toast notification\r\n        $RawXml = [xml] @\"\r\n&lt;toast&gt;\r\n    &lt;visual&gt;\r\n        &lt;binding template='ToastGeneric'&gt;\r\n            &lt;image placement='appLogoOverride' src='$ImagePath'\/&gt;\r\n            &lt;text id='1'&gt;$ToastTitle&lt;\/text&gt;\r\n            &lt;text id='2'&gt;$ToastText&lt;\/text&gt;\r\n        &lt;\/binding&gt;\r\n    &lt;\/visual&gt;\r\n    &lt;actions&gt;\r\n        $SnoozeXml\r\n        &lt;\/input&gt;\r\n        &lt;action activationType=\"system\" arguments=\"snooze\" hint-inputId=\"snoozeTime\" content=\"\" \/&gt;\r\n        &lt;action activationType=\"system\" arguments=\"dismiss\" content=\"\"\/&gt;\r\n    &lt;\/actions&gt;\r\n&lt;\/toast&gt;\r\n\"@\r\n\r\n        # Serialized Xml for later consumption\r\n        $SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument\r\n        $SerializedXml.LoadXml($RawXml.OuterXml)\r\n\r\n        # Setup how are toast will act, such as expiration time\r\n        $Toast = $null\r\n        $Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml)\r\n        $Toast.Tag = \"PowerShell\"\r\n        $Toast.Group = \"PowerShell\"\r\n\r\n        # Show our message to the user\r\n        $ToastNotifier.Show($Toast)\r\n    }\r\n}\r\nprocess {\r\n    Write-Host \"ApplicationID: $ApplicationId\"\r\n\r\n    if (-not $(Split-Path -Path $ImagePath -Parent | Test-Path -ErrorAction SilentlyContinue)) {\r\n        try {\r\n            New-Item \"$(Split-Path -Path $ImagePath -Parent)\" -ItemType Directory -ErrorAction Stop\r\n            Write-Host \"[Info] Created folder: $(Split-Path -Path $ImagePath -Parent)\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] Failed to create folder: $(Split-Path -Path $ImagePath -Parent)\"\r\n            exit 1\r\n        }\r\n    }\r\n\r\n    $DownloadArguments = @{\r\n        URL  = $PathToImageFile\r\n        Path = $ImagePath\r\n    }\r\n\r\n    Set-RegKey -Path \"HKCU:\\SOFTWARE\\Classes\\AppUserModelId\\$($ApplicationId -replace '\\s+','.')\" -Name \"DisplayName\" -Value $ApplicationId -PropertyType String\r\n    if ($PathToImageFile -like \"http*\") {\r\n        Invoke-Download @DownloadArguments\r\n    }\r\n    elseif ($PathToImageFile -match \"^[a-zA-Z]:\\\\\" -and $(Test-Path -Path $PathToImageFile -ErrorAction SilentlyContinue)) {\r\n        Write-Host \"[Info] Image is a local file, copying to $ImagePath\"\r\n        Copy-Item -Path $PathToImageFile -Destination $ImagePath\r\n    }\r\n    elseif ($PathToImageFile -match \"^[a-zA-Z]:\\\\\" -and -not $(Test-Path -Path $PathToImageFile -ErrorAction SilentlyContinue)) {\r\n        Write-Host \"[Error] Image does not exist at $PathToImageFile\"\r\n        exit 1\r\n    }\r\n    else {\r\n        Write-Host \"[Info] No image given, converting base64 on line 43 and saving to $ImagePath.\"\r\n        Write-Host \"[Info] Image will be used for the toast message.\"\r\n        ConvertFrom-Base64 -Base64 $Base64 -Path $ImagePath\r\n    }\r\n\r\n    Set-RegKey -Path \"HKCU:\\SOFTWARE\\Classes\\AppUserModelId\\$($ApplicationId -replace '\\s+','.')\" -Name \"IconUri\" -Value \"$ImagePath\" -PropertyType String\r\n\r\n    Write-Host \"[Info] System is ready to send Toast Messages to the currently logged on user.\"\r\n\r\n    try {\r\n        Write-Host \"[Info] Attempting to send message to user...\"\r\n        $NotificationParams = @{\r\n            ToastTitle    = $Title\r\n            ToastText     = $Message\r\n            ApplicationId = \"$($ApplicationId -replace '\\s+','.')\"\r\n            SnoozeOptions = $SnoozeTimeOptionsInMinutes\r\n        }\r\n        Show-Notification @NotificationParams -ErrorAction Stop\r\n        Write-Host \"[Info] Message sent to user.\"\r\n    }\r\n    catch {\r\n        Write-Host \"[Error] Failed to send message to user.\"\r\n        Write-Host $_.Exception.Message\r\n        exit 1\r\n    }\r\n    exit 0\r\n}\r\nend {\r\n    \r\n    \r\n    \r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"in-context-cta\"><p>Gagnez du temps gr\u00e2ce \u00e0 plus de 300 scripts du Dojo NinjaOne.<\/p>\n<p>\u2192 <a class=\"waffle-rich-text-link\" href=\"https:\/\/www.ninjaone.com\/fr\/phase-de-test-gratuit\/\">Obtenir l&rsquo;acc\u00e8s<\/a><\/p>\n<\/div>\n<h2>Description d\u00e9taill\u00e9e<\/h2>\n<p>Le script PowerShell fourni comprend plusieurs composants cl\u00e9s con\u00e7us pour la flexibilit\u00e9 et la fonctionnalit\u00e9. Voici une description d\u00e9taill\u00e9e de son fonctionnement\u00a0:<\/p>\n<h3>1. Initialisation et param\u00e8tres<\/h3>\n<ul>\n<li>Le script accepte des param\u00e8tres pour le titre de la notification, le message, l&rsquo;ID de l&rsquo;application, les options de remise \u00e0 plus tard (snooze) et un chemin d&rsquo;acc\u00e8s facultatif au fichier image.<\/li>\n<li>Il valide les entr\u00e9es et d\u00e9finit des valeurs par d\u00e9faut lorsque les param\u00e8tres ne sont pas fournis. Par exemple, l&rsquo;ApplicationId par d\u00e9faut est \u00ab\u00a0NinjaOne RMM\u00a0\u00bb, ce qui garantit la coh\u00e9rence de l&rsquo;identification dans le centre de notification Windows.<\/li>\n<\/ul>\n<h3>2. Validation par l&rsquo;utilisateur<\/h3>\n<ul>\n<li>Le script v\u00e9rifie s&rsquo;il est ex\u00e9cut\u00e9 en tant qu'\u00a0\u00bbutilisateur actuellement connect\u00e9\u00a0\u00bb Cela permet de s&rsquo;assurer que les notifications parviennent au destinataire pr\u00e9vu plut\u00f4t que d&rsquo;\u00eatre ex\u00e9cut\u00e9es dans un contexte de syst\u00e8me \u00e9lev\u00e9 o\u00f9 les notifications toast ne sont pas prises en charge.<\/li>\n<\/ul>\n<h3>3. Configuration du registre<\/h3>\n<ul>\n<li>\u00c0 l&rsquo;aide de la fonction Set-RegKey, le script cr\u00e9e ou met \u00e0 jour des entr\u00e9es de registre pour enregistrer l&rsquo;identifiant de l&rsquo;application de notification toast et associer une ic\u00f4ne \u00e0 la notification.<\/li>\n<\/ul>\n<h3>4. Traitement des images<\/h3>\n<p>Les notifications peuvent inclure une image personnalis\u00e9e. Le script prend en charge trois sc\u00e9narios\u00a0:<\/p>\n<ul>\n<li>URL pour t\u00e9l\u00e9charger une image.<\/li>\n<li>Chemin d&rsquo;acc\u00e8s au fichier local \u00e0 copier.<\/li>\n<li>Logo NinjaOne par d\u00e9faut encod\u00e9 en base64, converti et enregistr\u00e9 en tant que fichier image si aucune image personnalis\u00e9e n&rsquo;est fournie.<\/li>\n<\/ul>\n<h3>5. G\u00e9n\u00e9ration d&rsquo;une notification XML<\/h3>\n<ul>\n<li>Le script g\u00e9n\u00e8re un code XML d\u00e9finissant la structure de la notification toast, y compris le titre, le texte, l&rsquo;image et les options de remise \u00e0 plus tard (snooze). La fonction Show-Notification utilise l&rsquo;API Windows Runtime pour afficher la notification toast.<\/li>\n<\/ul>\n<h3>6. Fonctionnalit\u00e9 \u00ab\u00a0Snooze et Ignorer\u00a0\u00bb (Snooze and Dismiss)<\/h3>\n<ul>\n<li>Les utilisateurs peuvent bloquer les notifications pour des dur\u00e9es pr\u00e9configur\u00e9es ou les rejeter compl\u00e8tement. Ces options sont d\u00e9finies dans le XML et permettent \u00e0 l&rsquo;utilisateur d&rsquo;interagir directement \u00e0 partir de la notification.<\/li>\n<\/ul>\n<h2>Cas d&rsquo;utilisation potentiels<\/h2>\n<h3>\u00c9tude de cas\u00a0: Notifications de mise \u00e0 jour du syst\u00e8me<\/h3>\n<p>Imaginez un administrateur informatique dans un environnement d&rsquo;entreprise qui pr\u00e9voit de d\u00e9ployer une mise \u00e0 jour critique du syst\u00e8me pendant la nuit. Pour s&rsquo;assurer que les utilisateurs sont inform\u00e9s, il utilisent ce script pour envoyer une notification toast intitul\u00e9e \u00ab\u00a0Notification de maintenance du syst\u00e8me\u00a0\u00bb avec le message \u00ab\u00a0Votre syst\u00e8me red\u00e9marrera \u00e0 2h00 du matin pour des mises \u00e0 jour\u00a0\u00bb. Cliquez sur le bouton \u00ab\u00a0Snooze\u00a0\u00bb ou \u00ab\u00a0Ignorer\u00a0\u00bb<\/p>\n<ul>\n<li><strong>Personnalisation<\/strong>\u00a0: La notification comprend le logo de l&rsquo;entreprise.<\/li>\n<li><strong>Options de remise \u00e0 plus tard (snooze)<\/strong>\u00a0: Les utilisateurs peuvent retarder le rappel de 15, 30 ou 60 minutes.<\/li>\n<li><strong>R\u00e9sultat<\/strong>\u00a0: L&rsquo;\u00e9quipe veille \u00e0 ce que les utilisateurs soient bien inform\u00e9s sans qu&rsquo;il soit n\u00e9cessaire d&rsquo;effectuer un suivi manuel.<\/li>\n<\/ul>\n<h2>Comparaisons<\/h2>\n<h3>M\u00e9thodes alternatives\u00a0:<\/h3>\n<ol>\n<li><strong>Outils de notification tiers<\/strong>\u00a0: Bien qu&rsquo;efficaces, ils peuvent manquer de capacit\u00e9s d&rsquo;int\u00e9gration et engendrer des co\u00fbts.<\/li>\n<li><strong>Notifications int\u00e9gr\u00e9es de la strat\u00e9gie de groupe de Windows<\/strong>\u00a0: Personnalisation limit\u00e9e et pas de fonction \u00ab\u00a0Snooze\u00a0\u00bb.<\/li>\n<\/ol>\n<p>Par rapport \u00e0 ces m\u00e9thodes, ce script PowerShell propose\u00a0:<\/p>\n<ul>\n<li>Personnalisation accrue gr\u00e2ce \u00e0 la prise en charge des images.<\/li>\n<li>Am\u00e9lioration de l&rsquo;exp\u00e9rience de l&rsquo;utilisateur gr\u00e2ce aux options Snooze\/Ignorer.<\/li>\n<li>Rentabilit\u00e9, gr\u00e2ce \u00e0 l&rsquo;exploitation des API Windows natives.<\/li>\n<\/ul>\n<h2>FAQ<\/h2>\n<h3>Q\u00a0: Le script peut-il \u00eatre ex\u00e9cut\u00e9 par un administrateur\u00a0?<\/h3>\n<p>Non, il doit \u00eatre ex\u00e9cut\u00e9 en tant qu&rsquo;utilisateur connect\u00e9 pour afficher correctement les notifications.<\/p>\n<h3>Q\u00a0: Que se passe-t-il si aucune image n&rsquo;est fournie\u00a0?<\/h3>\n<p>Un logo NinjaOne par d\u00e9faut est utilis\u00e9, garantissant que chaque notification est personnalis\u00e9e.<\/p>\n<h3>Q\u00a0: Comment les options de remise \u00e0 plus tard (snooze) sont-elles configur\u00e9es\u00a0?<\/h3>\n<p>Les dur\u00e9es entre chaque affichage sont d\u00e9finies sous la forme d&rsquo;une liste s\u00e9par\u00e9e par des virgules (par exemple, \u00ab\u00a015,30,60\u00a0\u00bb pour 15, 30 et 60 minutes).<\/p>\n<h3>Q\u00a0: Est-il compatible avec les \u00e9ditions Windows IoT\u00a0?<\/h3>\n<p>Non, en raison de l&rsquo;absence de shell dans les \u00e9ditions IoT.<\/p>\n<h2>Implications<\/h2>\n<p>Gr\u00e2ce \u00e0 ce script, les \u00e9quipes informatiques peuvent standardiser l&rsquo;envoi des notifications, en veillant \u00e0 ce que les messages soient interactifs et pertinents. Dans les environnements plus vastes, cela am\u00e9liore la sensibilisation des utilisateurs et r\u00e9duit les p\u00e9riodes d&rsquo;inactivit\u00e9 dues \u00e0 des alertes manqu\u00e9es. De plus, les options de personnalisation aident les entreprises MSP \u00e0 renforcer leur identit\u00e9 tout en conservant leur professionnalisme.<\/p>\n<h2>Recommandations<\/h2>\n<ul>\n<li><strong>Testez le script dans un environnement hors production<\/strong>\u00a0: Validez le comportement du script dans un environnement contr\u00f4l\u00e9 avant de le d\u00e9ployer \u00e0 grande \u00e9chelle.<\/li>\n<li><strong>Personnalisez les identifiants de l&rsquo;application<\/strong>\u00a0: Utilisez des identifiants propres \u00e0 l&rsquo;entreprise pour une meilleure gestion et une meilleure visibilit\u00e9.<\/li>\n<li><strong>Suivez les r\u00e9actions des utilisateurs<\/strong>\u00a0: Recueillez des informations pour affiner les options de r\u00e9p\u00e9tition et le contenu des notifications afin de maximiser l&rsquo;engagement de l&rsquo;utilisateur.<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>Ce script illustre la mani\u00e8re dont <a href=\"https:\/\/www.ninjaone.com\/fr\/\">NinjaOne<\/a> et d&rsquo;autres solutions de gestion informatique similaires peuvent renforcer les capacit\u00e9s des professionnels de l&rsquo;informatique. En combinant simplicit\u00e9 et personnalisation avanc\u00e9e, le script permet une communication <a href=\"https:\/\/www.ninjaone.com\/fr\/efficacite\">efficace<\/a> et am\u00e9liore l&rsquo;exp\u00e9rience de l&rsquo;utilisateur. Que vous soyez un MSP ou une \u00e9quipe informatique interne, l&rsquo;utilisation d&rsquo;outils de ce type est conforme aux bonnes pratiques de gestion des op\u00e9rations informatiques.<\/p>\n<p>Pour des solutions plus personnalis\u00e9es, NinjaOne propose une suite d&rsquo;outils con\u00e7us pour rationaliser les flux de travail informatiques et optimiser la fiabilit\u00e9 des syst\u00e8mes.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"no","_lmt_disable":""},"operating_system":[4212],"use_cases":[4289],"class_list":["post-390389","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows","use_cases-gestion-des-utilisateurs-et-des-acces"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/script_hub\/390389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/comments?post=390389"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/media?parent=390389"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/operating_system?post=390389"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/use_cases?post=390389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}