A Customisable WPF MessageBox for PowerShell

Update 2017-08-25 | Changed the way the output from a button click is handled, saving it to a variable instead.

The humble VBScript message box has been around for a while now and is still a useful way of providing a simple pop-up notification in Windows. I’ve used it in my PowerShell scripts as well as my UI tools and even in my ConfigMgr task sequences for providing feedback to the end user.

WscriptMsgBox

Both WinForms and WPF also have a message box but they have similar style and functionality to the VBScript version.  In this age of modern design languages like Metro and Material Design however, this message box is starting to look a little dated. So I decided to create my own customizable message box in WPF as a PowerShell function that can be used in my scripts and UI tools.

Enter New-WPFMessageBox. My goal was to create a good-looking, fully-functional message box window that is highly customizable in the WPF format, and can even be used as a window host to display custom WPF content. The message box has a basic default design, but if you’re the creative type then you can customize away until you get an appearance you like.

Examples

Let’s have a look at some ways we can use this function.

To create a simple message box, all you need to do is pass a string to the Content parameter:


New-WPFMessageBox -Content "I'm a WPF Object!"

img2

The Content parameter is the only mandatory parameter, and can take either a simple text string or your own custom WPF content (which we’ll look at later).

To add a header, simply use the Title parameter:


New-WPFMessageBox -Content "I'm a WPF Object!" -Title "Custom Message Box"

img1

The title bar is a color block, so it can be used to create a nice contrast with the main content, for example. Use the TitleBackground parameter to change the color. This parameter is a dynamic parameter and will allow you to select from the list of available colors in the .Net palette.

img3

 

New-WPFMessageBox -Content "I'm a WPF Object!" -Title "Custom Message Box" -TitleBackground CornflowerBlue

img4

You can change the fonts, font weights and font sizes, as well as the background and foreground colors to create some nice combinations. The FontFamily parameter is also dynamic and allows you to select from fonts available in .Net.

The Content… parameters allow you to change the main content section, and the Title… parameters allow you to change the title.

When using several parameters, it can be easier to ‘splat’ them like so:


$Params = @{
    Content = "I'm a WPF Object!"
    Title = "Custom Message Box"
    TitleBackground = "CornflowerBlue"
    TitleFontSize = 28
    TitleFontWeight = "Bold"
    TitleTextForeground = "SpringGreen"
    ContentFontSize = 18
    ContentFontWeight = "Medium"
    ContentTextForeground = "SpringGreen"
}

New-WPFMessageBox @Params

img5

Use ContentBackground to change the main content background:

img6

You can change the button color using ButtonTextForeground:

img7

The default button is the OK button, but you can also use other buttons or button combinations such as Yes/No, Retry/Cancel, Abort/Retry/Ignore etc. Simply select an option using the ButtonType parameter.


$Params = @{
    Content = "The file 'Important Document.docx' could not be deleted."
    Title = "File Deletion Error"
    TitleBackground = "LightGray"
    TitleFontSize = 28
    TitleFontWeight = "Bold"
    TitleTextForeground = "Red"
    ContentFontSize = 18
    ContentFontWeight = "Medium"
}

New-WPFMessageBox @Params -ButtonType Abort-Retry-Ignore

img8

When a button is clicked, the text of the button is saved to a variable named WPFMessageBoxOutput so you can handle this in your code and perform different actions depending on what was clicked, eg:


New-WPFMessageBox @Params -ButtonType Abort-Retry-Ignore
If ($WPFMessageBoxOutput -eq "Abort")
{
    Exit
}
ElseIf ($WPFMessageBoxOutput -eq "Retry")
{
    <TryAgain>
}
Else
{
    <Continue>
}

You can also add your own custom buttons. Set the ButtonType to None, and pass the text for your buttons to the CustomButtons parameter:


$Params = @{
    Content = "The purchase order has been created.  Do you want to go ahead?"
    Title = "Purchase Order"
    TitleFontSize = 20
    TitleBackground = 'Green'
    TitleTextForeground = 'White'
    ButtonType = 'None'
    CustomButtons = "Yes, go ahead!","No, don't do it!", "Save it for later"
}
New-WPFMessageBox @Params

img9

You can create Information, Warning or Error message boxes using your own style. If you define the parameters once in your script, then you can simply call them everytime you want to display that message type.

A simple informational message:


$InfoParams = @{
    Title = "INFORMATION"
    TitleFontSize = 20
    TitleBackground = 'LightSkyBlue'
    TitleTextForeground = 'Black'
}
New-WPFMessageBox @InfoParams -Content "The server has been rebooted at 08:35 on 16th January 2017"

img10

A warning message:


$WarningParams = @{
    Title = "WARNING"
    TitleFontSize = 20
    TitleBackground = 'Orange'
    TitleTextForeground = 'Black'
}
New-WPFMessageBox @WarningParams -Content "The file could not be opened."

img11

An error message:


$ErrorMsgParams = @{
    Title = "ERROR!"
    TitleBackground = "Red"
    TitleTextForeground = "WhiteSmoke"
    TitleFontWeight = "UltraBold"
    TitleFontSize = 20
    Sound = 'Windows Exclamation'
}
New-WPFMessageBox @ErrorMsgParams -Content "There was a problem connecting to the Exchange Server.
Please try again later."

In this one I’ve added the Sound parameter. This is a dynamic parameter allowing you to select from available Windows sounds in your local media library. The sound will be played when the message box is displayed.

img12

Maybe you prefer a little more drama in your error message box. How about this:


$ErrorMsgParams = @{
    TitleBackground = "Red"
    TitleTextForeground = "Yellow"
    TitleFontWeight = "UltraBold"
    TitleFontSize = 28
    ContentBackground = 'Red'
    ContentFontSize = 18
    ContentTextForeground = 'White'
    ButtonTextForeground = 'White'
    Sound = 'Windows Hardware Fail'
}
$ComputerName = "DoesntExist"
Try
{
    New-PSSession -ComputerName $ComputerName -ErrorAction Stop
}
Catch
{
    New-WPFMessageBox @ErrorMsgParams -Content "$_" -Title "PSSession Error!"
}

In this code, I am using a try / catch block to catch an error, then using the message box to display it.

img13

Or we can create a Windows 10 BSOD-style error:


$Params = @{
    FontFamily = 'Verdana'
    Title = ":("
    TitleFontSize = 80
    TitleTextForeground = 'White'
    TitleBackground = 'SteelBlue'
    ButtonType = 'OK'
    ContentFontSize = 16
    ContentTextForeground = 'White'
    ContentBackground = 'SteelBlue'
    ButtonTextForeground = 'White'
    BorderThickness = 0
}
New-WPFMessageBox @Params -Content = "The script ran into a problem that it couldn't handle, and now it needs to exit.

0x80050002"

img14

If you prefer square corners and no window shadow effect for a more basic look, try this. Here I have set the CornerRadius, ShadowDepth and BlurRadius to 0, as well as setting the BorderThickness and BorderBrush parameters to create a simple border.


$Params = @{
    Title = "QUESTION"
    TitleBackground ='Navy'
    TitleTextForeground = 'White'
    ButtonType = 'Yes-No'
    CornerRadius = 0
    ShadowDepth = 0
    BlurRadius = 0
    BorderThickness = 1
    BorderBrush = 'Navy'

}
New-WPFMessageBox @Params -Content "The server is not online. Do you wish to proceed?"

img15

You can create some interesting effects with those parameters, such as a more circular window:


$Params = @{
    Title = "QUESTION"
    TitleBackground ='Navy'
    TitleTextForeground = 'White'
    ButtonType = 'Yes-No'
    CornerRadius = 80
    ShadowDepth = 5
    BlurRadius = 5
    BorderThickness = 1
    BorderBrush = 'Navy'

}
New-WPFMessageBox @Params -Content "The server is not online.
Do you wish to proceed?"

img16

Timeout is a useful parameter which allows you to automatically close the message box after a number of seconds. You might want to use this in a script where you choose to continue if no response was received after a period of time. You can also use this to simply display a message without any buttons – just for information, and no response is required.


$Content = "Your mission - which we have chosen to accept for you - is to eliminate Windows XP in the enterprise.
Good luck!

This message will self-destruct in 30 seconds"

$Params = @{
    Content = $Content
    Title = "MISSION:POSSIBLE"
    TitleFontSize = 30
    TitleTextForeground = 'Red'
    TitleFontWeight = 'Bold'
    TitleBackground = 'Silver'
    FontFamily = 'Lucida Console'
    ButtonType = 'None'
    Timeout = 30
}

New-WPFMessageBox @Params

img30

I’ve also added a couple of parameters that allow you to assign code to the Loaded or Closed events on the message box window. This means you can run code when the message box opens, or after it has closed. Simply pass a code block to the OnLoaded or OnClosed parameters. Bear in mind that any code assigned to the Loaded event should not be long running as it will block the thread until it has completed, and the message box will only display afterwards.

In this example, I have used an async method from the SpeechSynthesizer class so that the text will be spoken at the same time the window opens because it is not running in the same thread.


$Content = "We could not access the server. Do you wish to continue?"

$Code = {
    Add-Type -AssemblyName System.speech
    (New-Object System.Speech.Synthesis.SpeechSynthesizer).SpeakAsync($Content)
    }

$Params = @{
    Content = "$Content"
    Title = "ERROR"
    ContentBackground = "WhiteSmoke"
    FontFamily = "Tahoma"
    TitleFontWeight = "Heavy"
    TitleBackground = "Red"
    TitleTextForeground = "YellowGreen"
    Sound = 'Windows Message Nudge'
    ButtonType = 'Cancel-TryAgain-Continue'
    OnLoaded = $Code
}

New-WPFMessageBox @Params

img31

Adding Custom WPF Content

As well as a simple text string, the Content parameter can accept a WPF UI element. When you pass a text string, the function simply creates a textblock element and adds the text. But if you know a little about creating WPF objects in PowerShell, you can create your own elements and add them as content to the message box. This opens up a lot of possibilities and transforms the message box into a kind of easy-to-create window host for any WPF content.

For example, instead of some text, how about displaying a picture instead?


$Source = "C:\Users\tjones\Pictures\minion.jpg"
$Image = New-Object System.Windows.Controls.Image
$Image.Source = $Source
$Image.Height = [System.Drawing.Image]::FromFile($Source).Height / 2
$Image.Width = [System.Drawing.Image]::FromFile($Source).Width / 2

New-WPFMessageBox -Content $Image -Title "Minions Rock!" -TitleBackground LightSeaGreen -TitleTextForeground Black

To set the height and width I have simply halved the dimensions of the source image file.

img17

Maybe you want to add a text description of the picture too. In that case, create a textblock and add both the image and textblock to a layout control like a stackpanel, and pass the stackpanel as content.


$Source = "C:\Users\tjones\Pictures\minion.jpg"
$Image = New-Object System.Windows.Controls.Image
$Image.Source = $Source
$Image.Height = [System.Drawing.Image]::FromFile($Source).Height / 2
$Image.Width = [System.Drawing.Image]::FromFile($Source).Width / 2

$TextBlock = New-Object System.Windows.Controls.TextBlock
$TextBlock.Text = "My friend Robert"
$TextBlock.FontSize = "28"
$TextBlock.HorizontalAlignment = "Center"

$StackPanel = New-Object System.Windows.Controls.StackPanel
$StackPanel.AddChild($Image)
$StackPanel.AddChild($TextBlock)

New-WPFMessageBox -Content $StackPanel -Title "Minions Rock!" -TitleBackground LightSeaGreen -TitleTextForeground Black -ContentBackground LightSeaGreen

img18

How about playing a video?


$MediaPlayer = New-Object System.Windows.Controls.MediaElement
$MediaPlayer.Height = "360"
$MediaPlayer.Width = "640"
$MediaPlayer.Source = "http://video.ch9.ms/ch9/5e56/5148ed00-c3cc-4d1b-a0e0-3f9cbfbb5e56/EmpoerBusinesstodoGreatThings.mp4"

New-WPFMessageBox -Content $MediaPlayer -Title "Windows 10 In The Enterprise"

$MediaPlayer.LoadedBehavior = "Manual"
$MediaPlayer.Stop()

img19

We could also add some buttons to control playback. I’ve added the buttons to a dockpanel, added both the video player and the dockpanel to a stackpanel, as use the stackpanel as content.


# Create a Media Element
$MediaPlayer = New-Object System.Windows.Controls.MediaElement
$MediaPlayer.Height = "360"
$MediaPlayer.Width = "640"
$MediaPlayer.LoadedBehavior = "Manual"
$MediaPlayer.Source = "http://video.ch9.ms/ch9/5e56/5148ed00-c3cc-4d1b-a0e0-3f9cbfbb5e56/EmpoerBusinesstodoGreatThings.mp4"

# Add a start button
$StartButton = New-Object System.Windows.Controls.Button
$StartButton.Content = "Start"
$StartButton.FontSize = 22
$StartButton.Width = "NaN"
$StartButton.Height = "NaN"
$StartButton.VerticalContentAlignment = "Center"
$StartButton.HorizontalContentAlignment = "Center"
$StartButton.HorizontalAlignment = "Center"
$StartButton.VerticalAlignment = "Center"
$StartButton.Background = "Transparent"
$StartButton.Margin = "0,5,15,0"
$StartButton.Padding = 10
$StartButton.Cursor = "Hand"
$StartButton.Add_Click({
    $MediaPlayer.Play()
})

# Add a stop button
$StopButton = New-Object System.Windows.Controls.Button
$StopButton.Content = "Stop"
$StopButton.FontSize = 22
$StopButton.Width = "NaN"
$StopButton.Height = "NaN"
$StopButton.VerticalContentAlignment = "Center"
$StopButton.HorizontalContentAlignment = "Center"
$StopButton.HorizontalAlignment = "Center"
$StopButton.VerticalAlignment = "Center"
$StopButton.Background = "Transparent"
$StopButton.Margin = "15,5,0,0"
$StopButton.Padding = 10
$StopButton.Cursor = "Hand"
$StopButton.Add_Click({
    $MediaPlayer.Stop()
})

# Add a pause button
$PauseButton = New-Object System.Windows.Controls.Button
$PauseButton.Content = "Pause"
$PauseButton.FontSize = 22
$PauseButton.Width = "NaN"
$PauseButton.Height = "NaN"
$PauseButton.VerticalContentAlignment = "Center"
$PauseButton.HorizontalContentAlignment = "Center"
$PauseButton.HorizontalAlignment = "Center"
$PauseButton.VerticalAlignment = "Center"
$PauseButton.Background = "Transparent"
$PauseButton.Margin = "15,5,15,0"
$PauseButton.Padding = 10
$PauseButton.Cursor = "Hand"
$PauseButton.Add_Click({
    $MediaPlayer.Pause()
})

# Add buttons to a dock panel
$DockPanel = New-object System.Windows.Controls.DockPanel
$DockPanel.LastChildFill = $False
$DockPanel.HorizontalAlignment = "Center"
$DockPanel.Width = "NaN"
$DockPanel.AddChild($StartButton)
$DockPanel.AddChild($PauseButton)
$DockPanel.AddChild($StopButton)

# Add dock panel and media player to a stackpanel
$StackPanel = New-object System.Windows.Controls.StackPanel
$StackPanel.AddChild($MediaPlayer)
$StackPanel.AddChild($DockPanel)

New-WPFMessageBox -Content $StackPanel -Title "Windows 10 In The Enterprise"

img20

Although I haven’t included any icons or images for message types like warning or error etc, you could still add your own using custom content:


$Image = New-Object System.Windows.Controls.Image
$Image.Source = "http://www.asistosgb.com/wp-content/uploads/2017/05/attent.png"
$Image.Height = 50
$Image.Width = 50
$Image.Margin = 5

$TextBlock = New-Object System.Windows.Controls.TextBlock
$TextBlock.Text = "The file could not be deleted at this time!"
$TextBlock.Padding = 10
$TextBlock.FontFamily = "Verdana"
$TextBlock.FontSize = 16
$TextBlock.VerticalAlignment = "Center"

$StackPanel = New-Object System.Windows.Controls.StackPanel
$StackPanel.Orientation = "Horizontal"
$StackPanel.AddChild($Image)
$StackPanel.AddChild($TextBlock)

New-WPFMessageBox -Content $StackPanel -Title "WARNING" -TitleFontSize 28 -TitleBackground Orange 

img21

How about including an expander for an error message box, with the error details available for viewing when expanded?


$ComputerName = "RandomPC"
Try
{
    New-PSSession -ComputerName $ComputerName -ErrorAction Stop
}
Catch
{

    # Create a text box
    $TextBox = New-Object System.Windows.Controls.TextBox
    $TextBox.Text = "Could not create a remote session to '$ComputerName'!"
    $TextBox.Padding = 5
    $TextBox.Margin = 5
    $TextBox.BorderThickness = 0
    $TextBox.FontSize = 16
    $TextBox.Width = "NaN"
    $TextBox.IsReadOnly = $True

    # Create an exander
    $Expander = New-Object System.Windows.Controls.Expander
    $Expander.Header = "Error details"
    $Expander.FontSize = 14
    $Expander.Padding = 5
    $Expander.Margin = "5,5,5,0"

    # Bind the expander width to the text box width, so the message box width does not change when expanded
    $Binding = New-Object System.Windows.Data.Binding
    $Binding.Path = [System.Windows.Controls.TextBox]::ActualWidthProperty
    $Binding.Mode = [System.Windows.Data.BindingMode]::OneWay
    $Binding.Source = $TextBox
    [void]$Expander.SetBinding([System.Windows.Controls.Expander]::WidthProperty,$Binding)

    # Create a textbox for the expander
    $ExpanderTextBox = New-Object System.Windows.Controls.TextBox
    $ExpanderTextBox.Text = "$_"
    $ExpanderTextBox.Padding = 5
    $ExpanderTextBox.BorderThickness = 0
    $ExpanderTextBox.FontSize = 16
    $ExpanderTextBox.TextWrapping = "Wrap"
    $ExpanderTextBox.IsReadOnly = $True
    $Expander.Content = $ExpanderTextBox

    # Assemble controls into a stackpanel
    $StackPanel = New-Object System.Windows.Controls.StackPanel
    $StackPanel.AddChild($TextBox)
    $StackPanel.AddChild($Expander)

    # Using no rounded corners as they do not stay true when the window resizes
    New-WPFMessageBox -Content $StackPanel -Title "PSSession Error" -TitleBackground Red -TitleFontSize 20 -Sound 'Windows Unlock' -CornerRadius 0
}

img22

img23

If your script returns data in table format, how about using a WPF datagrid to display it in a nicer way? You can populate a datagrid from an array, but I recommend converting to a datatable object as it’s a type that fully supports the features of the datagrid.
In this example, I’m simply displaying services on my system from the Get-Service cmdlet.


# Get Services
$Fields = @(
    'Status'
    'DisplayName'
    'ServiceName'
)
$Services = Get-Service | Select $Fields

# Add Services to a datatable
$Datatable = New-Object System.Data.DataTable
[void]$Datatable.Columns.AddRange($Fields)
foreach ($Service in $Services)
{
    $Array = @()
    Foreach ($Field in $Fields)
    {
        $array += $Service.$Field
    }
    [void]$Datatable.Rows.Add($array)
}

# Create a datagrid object and populate with datatable
$DataGrid = New-Object System.Windows.Controls.DataGrid
$DataGrid.ItemsSource = $Datatable.DefaultView
$DataGrid.MaxHeight = 500
$DataGrid.MaxWidth = 500
$DataGrid.CanUserAddRows = $False
$DataGrid.IsReadOnly = $True
$DataGrid.GridLinesVisibility = "None"

$Params = @{
    Content = $DataGrid
    Title = "Services on $Env:COMPUTERNAME"
    ContentBackground = "WhiteSmoke"
    FontFamily = "Tahoma"
    TitleFontWeight = "Heavy"
    TitleBackground = "LightSteelBlue"
    TitleTextForeground = "Black"
    Sound = 'Windows Message Nudge'
    ContentTextForeground = "DarkSlateGray"
}
New-WPFMessageBox @Params

img24

How about using a TreeView object to group the services by status?


$TreeView = New-Object System.Windows.Controls.TreeView
$TreeView.MaxHeight = 500
$TreeView.Height = 400
$TreeView.Width = 400
$TreeView.BorderThickness = 0
"Running","Stopped" | foreach {
    $Item = New-Object System.Windows.Controls.TreeViewItem
    $Item.Padding = 5
    $Item.FontSize = 16
    $Item.Header = $_
    [void]$TreeView.Items.Add($Item)
}
$TreeView.Items[0].ItemsSource = Get-Service | Where {$_.Status -eq "Running"} | Select -ExpandProperty DisplayName
$TreeView.Items[1].ItemsSource = Get-Service | Where {$_.Status -eq "Stopped"} | Select -ExpandProperty DisplayName

New-WPFMessageBox -Content $TreeView -Title "Services by Status" -TitleBackground "LightSteelBlue"

img25

If you want to use the message box function in your own WPF UI tool, then you can use the WindowHost parameter to pass the host window object. This will make the host window owner of the message box window, and means your message box will always display centered in the host window, no matter the size or location of the window.

In this example I have created a simple host window with a big “Click Me” button. When clicked, a message box will display.


$Window = New-object System.Windows.Window
$Window.WindowStartupLocation = "CenterScreen"
$Window.SizeToContent="WidthAndHeight"
$Button = New-Object System.Windows.Controls.Button
$Button.Content = "Click Me!"
$Button.FontSize = 28
$Button.HorizontalAlignment = "Center"
$Button.VerticalAlignment = "Center"
$Button.Height = 300
$Button.Width = "400"
$Button.Background = "WhiteSmoke"
$Button.BorderThickness = 0
$Window.AddChild($Button)

$Button.Add_Click({
    New-WPFMessageBox -Content "This Content box is owned by the parent window and will be positioned centrally in the window." -Title "WPF Content Box" -TitleBackground Coral -WindowHost $Window
})

$Window.ShowDialog()

img26

img27

My final example is a bit more advanced, but it demonstrates how the message box could be used in a more dynamic way to display output from code running in a background job.

I’ve created a stackpanel from XAML code containing a textbox and a button.  These are all added to a synchronized hash table which gets passed, together with a code block, to a new PowerShell instance which runs in the background. The code block simply pings a list of computers in succession and updates the textbox in real time with the result of each ping.

The background job is triggered by the “Begin” button.


# XAML code
[XML]$Xaml = @"
<StackPanel          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <TextBox ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" Name="TextBox" Width="400" Height="200" Text="" BorderThickness="0" FontSize="18" TextWrapping="Wrap" FontFamily="Arial" IsReadOnly="True" Padding="5"/>
    <Button Name="Button" Content="Begin" Background="White" FontSize="24" HorizontalAlignment="Center" Cursor="Hand" />
</StackPanel>
"@

# Create the WPF object from the XAML code
$ChildElement = [Windows.Markup.XamlReader]::Load((New-Object -TypeName System.Xml.XmlNodeReader -ArgumentList $xaml))

# Create a synchronised hashtable and add elements to it
$UI = [System.Collections.Hashtable]::Synchronized(@{})
$UI.ChildElement = $ChildElement
$UI.TextBox = $ChildElement.FindName('TextBox')
$UI.Button = $ChildElement.FindName('Button')

# Define the code to run in a background job
$Code = {
    Param($UI)

    # Disable the button during run
    $UI.TextBox.Dispatcher.Invoke({
        $UI.Button.IsEnabled=$False
        $UI.Button.Foreground="Gray"
    })

    # Ping IP addresses
    10..20 | foreach {
        $Index = $_
        $IPaddress = "10.25.24.$Index"
        If (Test-Connection -ComputerName $IPaddress -Count 1 -Quiet)
        {
            $UI.TextBox.Dispatcher.Invoke({
                $UI.TextBox.Text = $UI.TextBox.Text + "`n" + "$IPAddress is online"
                $UI.TextBox.ScrollToEnd()
            })
        }
        Else
        {
            $UI.TextBox.Dispatcher.Invoke({
                $UI.TextBox.Text = $UI.TextBox.Text + "`n" + "$IPAddress could not be contacted"
                $UI.TextBox.ScrollToEnd()
            })
        }
    }

    # Re-enable button
    $UI.TextBox.Dispatcher.Invoke({
        $UI.Button.IsEnabled=$True
        $UI.Button.Foreground="Black"
    })
}

# Define the code to run when the button is clicked
$UI.Button.Add_Click({

    # Spin up a powershell instance and run the code
    $PowerShell = [powershell]::Create()
    $PowerShell.AddScript($Code)
    $PowerShell.AddArgument($UI)
    $PowerShell.BeginInvoke()

})

New-WPFMessageBox -Title "Test-Connection Log Window" -Content $ChildElement

Ping

You could also run the code automatically when the message box opens by using the OnLoaded parameter, or by subscribing to the Loaded event on one of the UI elements instead of the button click, eg:


$UI.TextBox.Add_Loaded({

    # Spin up a powershell instance and run the code
    $PowerShell = [powershell]::Create()
    $PowerShell.AddScript($Code)
    $PowerShell.AddArgument($UI)
    $PowerShell.BeginInvoke()

})

# or...

$OnLoadedCode = {

    # Spin up a powershell instance and run the code
    $PowerShell = [powershell]::Create()
    $PowerShell.AddScript($Code)
    $PowerShell.AddArgument($UI)
    $PowerShell.BeginInvoke()

}

New-WPFMessageBox -Title "Test-Connection Log Window" -Content $ChildElement -OnLoaded $OnLoadedCode

})

And I’m done. Try it out!

Btw, here’s the code 🙂

Advertisements

9 thoughts on “A Customisable WPF MessageBox for PowerShell

  1. Wauw, cool message boxes, thank you so much. Only minor suggestion to include default icons for information,warning and error messages would be nice, so I don’t need to get an external image somewhere..but now I’m just whining. Keep up your great posts, much appreciated!

  2. This is a great help!! Is there a way to force the WPF window to open in front of other windows? I find sometimes it pops up behind another so the user misses the message.

    Thanks
    Andy

    1. That’s interesting, the $this.activate() line should take care of that. Another way to do it is to set the topmost property of the window, so set $window.topmost = $true just after the window object is created, then set it back to false in the $window.Add_loaded event methods otherwise the window will stay permanently on top of all other windows.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s