PowerShell PopUp

popupAt the recent PowerShell Summit I presented a session on adding graphical elements to your script without the need for WinForms or WPF. One of the items I demonstrated is a graphical popup that can either require the user to click a button or automatically dismiss after a set time period. If this sounds familiar, yes, it is our old friend VBScript and the Popup method of the Wscript.Shell object. Because PowerShell can create and use COM objects, why not take advantage of this?

All it really takes is two lines. One line to create the Wscript.Shell COM object and one to invoke the Popup method.  (Yes, I’m sure you could do this in one line, but that’s not the point.)

$wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
$wshell.Popup("Are you looking at me?",0,"Hey!",48+4)

The Popup method needs parameters for the message, title, a timeout value, and an integer value that represents a combination of buttons and icons.

popup2The challenging part has always been trying to remember the integer values. So I wrote a quick function called New-Popup.

#requires -version 2.0

Function New-Popup {

<#
.Synopsis
Display a Popup Message
.Description
This command uses the Wscript.Shell PopUp method to display a graphical message
box. You can customize its appearance of icons and buttons. By default the user
must click a button to dismiss but you can set a timeout value in seconds to 
automatically dismiss the popup. 

The command will write the return value of the clicked button to the pipeline:
  OK     = 1
  Cancel = 2
  Abort  = 3
  Retry  = 4
  Ignore = 5
  Yes    = 6
  No     = 7

If no button is clicked, the return value is -1.
.Example
PS C:\> new-popup -message "The update script has completed" -title "Finished" -time 5

This will display a popup message using the default OK button and default 
Information icon. The popup will automatically dismiss after 5 seconds.
.Notes
Last Updated: April 8, 2013
Version     : 1.0

.Inputs
None
.Outputs
integer

Null   = -1
OK     = 1
Cancel = 2
Abort  = 3
Retry  = 4
Ignore = 5
Yes    = 6
No     = 7
#>

Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a message for the popup")]
[ValidateNotNullorEmpty()]
[string]$Message,
[Parameter(Position=1,Mandatory=$True,HelpMessage="Enter a title for the popup")]
[ValidateNotNullorEmpty()]
[string]$Title,
[Parameter(Position=2,HelpMessage="How many seconds to display? Use 0 require a button click.")]
[ValidateScript({$_ -ge 0})]
[int]$Time=0,
[Parameter(Position=3,HelpMessage="Enter a button group")]
[ValidateNotNullorEmpty()]
[ValidateSet("OK","OKCancel","AbortRetryIgnore","YesNo","YesNoCancel","RetryCancel")]
[string]$Buttons="OK",
[Parameter(Position=4,HelpMessage="Enter an icon set")]
[ValidateNotNullorEmpty()]
[ValidateSet("Stop","Question","Exclamation","Information" )]
[string]$Icon="Information"
)

#convert buttons to their integer equivalents
Switch ($Buttons) {
    "OK"               {$ButtonValue = 0}
    "OKCancel"         {$ButtonValue = 1}
    "AbortRetryIgnore" {$ButtonValue = 2}
    "YesNo"            {$ButtonValue = 4}
    "YesNoCancel"      {$ButtonValue = 3}
    "RetryCancel"      {$ButtonValue = 5}
}

#set an integer value for Icon type
Switch ($Icon) {
    "Stop"        {$iconValue = 16}
    "Question"    {$iconValue = 32}
    "Exclamation" {$iconValue = 48}
    "Information" {$iconValue = 64}
}

#create the COM Object
Try {
    $wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
    #Button and icon type values are added together to create an integer value
    $wshell.Popup($Message,$Time,$Title,$ButtonValue+$iconValue)
}
Catch {
    #You should never really run into an exception in normal usage
    Write-Warning "Failed to create Wscript.Shell COM object"
    Write-Warning $_.exception.message
}

} #end function

The function lets you use text descriptions for the buttons and icons. In PowerShell 3.0 you will also get tab completion for the possible values. This makes it easy to create a command like this:

new-popup "Do you want to get work done with PowerShell?" -Title "Hey, you!" -Buttons YesNo -Icon Question

The function writes the value of the clicked button to the pipeline. I expect this is something you are more apt to use in a script. Perhaps to display an error message or even to prompt the user for an action. Maybe you’d like to use it in your PowerShell 3.0 profile:

$r = New-Popup -Title "Help Update" -Message "Do you want to update help now?" -Buttons YesNo -Time 5 -Icon Question
if ($r -eq 6) {
  Update-Help -SourcePath \\jdh-nvnas\files\PowerShell_Help -Force
}

The popup will automatically dismiss after 5 seconds unless I click Yes or No. You should be able to copy the function text from the listing above by toggling to plain code, select all and copy.

I hope you’ll let me know where you use this.

About the Author

PowerShell.org Announcer

This is the official account for PowerShell.org and sponsor announcements.