powershellsessionwindowscheduled-tasksnotifyicon

[Windows 10][Powershell] Attach a System.Windows.Forms.NotifyIcon object to a user session in a PS script launched by the system


I have a Powershell script which takes care of launching a backup software and which is started by a scheduled task under the system user. I can't use the user session, because I need to have full admin rights on the disk and also run the backup even if there is no user logged in.

I would like to display a notification and an icon in the taskbar to have a visual indicator and avoid as much as possible shutting down the computer when a backup is in progress.

So I put in my Powershell script the following code to create the notification:

$iconPath = "C:\icon.ico"
$icon = New-Object System.Drawing.Icon $iconPath

$notification = New-Object System.Windows.Forms.NotifyIcon
$notification.Icon = $icon
$notification.Visible = $true
$notification.ShowBalloonTip(5000, "Burp backup started", "", [System.Windows.Forms.ToolTipIcon]::Info)

#... backup starting commands

$notification.ShowBalloonTip(5000, "Burp backup finished", "", [System.Windows.Forms.ToolTipIcon]::Info)
$notification.Dispose()

The problem is that the notification does not appear when the script is launched by the scheduled task (but it works correctly when the script is launched manually).

I guess it's because the user launching the task is System and so it doesn't have the desktop/explorer context of the session to display the interface.

Is there a way to attach the notification to a logged in user session? Knowing that in my case, there is only one user on the computer and that I know the username to search for.


Solution

  • Your requirements prevent a simple solution:

    You can use the following techniques to interact with the user from a service on all supported versions of Windows:

    • [NOT AN OPTION IN YOUR CASE] Display a dialog box in the user's session using the WTSSendMessage function.

    • Create a separate hidden GUI application and use the CreateProcessAsUser function to run the application within the context of the interactive user. Design the GUI application to communicate with the service through some method of interprocess communication (IPC), for example, named pipes. The service communicates with the GUI application to tell it when to display the GUI. The application communicates the results of the user interaction back to the service so that the service can take the appropriate action. Note that IPC can expose your service interfaces over the network unless you use an appropriate access control list (ACL).
      .
      If this service runs on a multiuser system, add the application to the following key so that it is run in each session: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. If the application uses named pipes for IPC, the server can distinguish between multiple user processes by giving each pipe a unique name based on the session ID.

    Note: As Doug Maurer points out: