PowerShell Pipeline

Creating a Balloon Tip Notification Using PowerShell

PowerShell makes it easy to create a custom pop-up notification in Windows.

There are a few ways that PowerShell can provide some sort of notification method to alert you when something happens such as a script completing or an issue is detected during a query. The most common notification in PowerShell would be the console host text that utilizes any of the Write-* cmdlets to write the text to the console. Common alerts for errors or warnings would be the Write-Error or Write-Warning cmdlets while using Write-Host would be common to let you know when something has completed.

Beyond the console, sometimes a more assertive approach is required to get the user's attention when something has completed or an issue is encountered. In that case, a pop-up window could be built and displayed to the user to acknowledge. This is done typically using the System.Windows.MessageBox type and using the proper method to display a message to the user.

Both of these are great and provide some sort of feedback to the user when needed, but another approach to notifications lies in the balloon tip. Most of us are familiar with balloon tips even if we may not have realized what they are. They can be from any program or system activity, but I know everyone is very familiar with the balloon tip that comes from the Windows update agent.

[Click on image for larger view.] Figure 1.

This particular balloon tip comes to us from Windows 7, but rest assured, these will work on Windows 10 as shown in the image below.

[Click on image for larger view.] Figure 2.

So how can we make this happen? Fortunately, we do not have to dive very deep into the rabbit hole to have access to this type of UI notification. That means no WPF creation with XAML or diving into Windows Forms to build out anything. Instead, we will only need to work with the System.Windows.Forms.NotifyIcon type to build our notification balloon tip. Note that we will need to add the System.Windows.Forms assembly into our PowerShell session before we can make use of the NotifyIcon class.

As I mentioned before, we should first load the assembly into our session.

Add-Type -AssemblyName System.Windows.Forms

With that out of the way, we can create our first NotifyIcon object and examine its properties and methods.

$global:balloon = New-Object System.Windows.Forms.NotifyIcon

You might be asking why I made this a global scope variable and I promise that the answer will be revealed shortly, but in the mean time we will now take a quick look at the members of this object and begin work to create our balloon tip!

Get-Member -InputObject $Global:balloon

[Click on image for larger view.] Figure 3.

There are a lot of properties and methods here along with some events that might prove useful for handling the tooltip icon that exists in the system tray, notably the MouseDoubleClick event.

Before we begin the process of setting the properties and ultimately calling the balloon tip, I want to create an event handler which will be used to remove the system tray icon when it is double clicked.

[void](Register-ObjectEvent -InputObject $balloon -EventName MouseDoubleClick -SourceIdentifier IconClicked -Action {

#Perform cleanup actions on balloon tip

$global:balloon.dispose()

Unregister-Event -SourceIdentifier IconClicked

Remove-Job -Name IconClicked

Remove-Variable -Name balloon -Scope Global

})

Now when the icon is double clicked, it will remove the icon by disposing of the NotifyIcon object as well as some cleanup of the actual event handling job itself.

Up next we can start building out the object by setting some of the properties. First off I will set the system tray icon of the PowerShell ISE by just locating its path via Get-Process and locating the Path property. After I have the path, I need to extract the icon from the file so it can be applied to the Icon property.

$path = (Get-Process -id $pid).Path

$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)

Using this approach, you can pull any icon from a file and use it for the system tray icon when the balloon tip is launched.

I want to provide an icon within the balloon tip similar to what I saw in the Windows update tip. To do this, I'll need to find the proper icon by looking at the static members of the System.Windows.Forms.ToolTipIcon class.

[System.Windows.Forms.ToolTipIcon] | Get-Member -Static -Type Property

[Click on image for larger view.] Figure 4.

I think I will make use of the Warning ToolTipIcon for this balloon tip.

$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning

Next up is to set a title and a message that will be displayed along with the balloon tip.

$balloon.BalloonTipText = 'What do you think of this balloon tip?'

$balloon.BalloonTipTitle = "Attention $Env:USERNAME"

The final thing that I will do is to set the visibility of the tool tip to $True and then we can look at launching the tip.

$balloon.Visible = $true

To make the balloon tip display, I will call the ShowBalloonTip method. There are a couple of parameter sets that I can look at using.

[Click on image for larger view.] Figure 5.

In this case, I am going to only specify an integer which says how long, in milliseconds, that the tip message will display before going away and just leaving the icon in the system tray.

I have decided that I will display the tool tip for five seconds, which means that I will use 5000 milliseconds when I call ShowBalloonTip.

$balloon.ShowBalloonTip(5000)

[Click on image for larger view.] Figure 6.

After I am done looking at this tip, I can simply double click on the PowerShell ISE icon that I used to close it.

Before I wrap this up, I decided to make a function called Invoke-BalloonTip, which you can find at my GitHub page that makes creating a balloon tip easier. Once you download the function, you can run it like this:

Invoke-BalloonTip -Message 'This is a message from my function' -Title 'Attention!' -MessageType Info

[Click on image for larger view.] Figure 7.

What we end up having is another approach to provide a notification to a user via a balloon tip versus using a console alert or popup. Now you can take what you have learned here and apply it to some of your own scripts!