Skip to the main content.

Unlocking the Power of PowerShell: Tips for Success

Using .NET Libraries in PowerShell - GUI dialogs and case-correcting text

In the previous two parts, we looked at a few .NET types and ways to “look inside” and find their hidden methods. This provided you with granular control, such as when rounding values.

Any .NET type follows these same rules, so now you’re ready to explore more with .NET types. In this part, we’ll look at GUI dialogs and case-correcting text.

 

Invoking Message Boxes

When a script emits data, it typically surfaces as text in the console, which can be easily overlooked by the user.

If your script needs to catch attention, a message box dialog may be a more effective way to do so. Here’s how to invoke such a dialog:

 


# loading the required .NET type 
Add-Type -AssemblyName PresentationFramework

$result = [System.Windows.MessageBox]::Show("I need to restart your server`r`n`r`nMay I proceed?", 'Attention', 'YesNo', 'Question')

if ($result -eq 'Yes')
{
  Write-Warning 'I am restarting...'
}
else
{
  Write-Warning 'Ok, I am aborting...'
} 

 

The .NET type we are using this time is [System.Windows.MessageBox]. For the first time in this series, this is a type that is not used by PowerShell. It is still present in the .NET (on Windows), but it is not loaded by default.

That’s why you need to run Add-Type first and instruct it to load the assembly (DLL) that defines this type. If you forget this, PowerShell will complain that it cannot find the type.

 

Examining Overloads

Let’s once again look at the overload definitions for the Show() method, just like we did in the past two parts:


PS C:\> [System.Windows.MessageBox]::Show

OverloadDefinitions                                                                                                                                                               
-------------------                                                                                                                                                               
static System.Windows.MessageBoxResult Show(string messageBoxText, string caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon,                   
System.Windows.MessageBoxResult defaultResult, System.Windows.MessageBoxOptions options)                                                                                          
static System.Windows.MessageBoxResult Show(string messageBoxText, string caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon,                   
System.Windows.MessageBoxResult defaultResult)                                                                                                                                    
static System.Windows.MessageBoxResult Show(string messageBoxText, string caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon)                   
static System.Windows.MessageBoxResult Show(string messageBoxText, string caption, System.Windows.MessageBoxButton button)                                                        
static System.Windows.MessageBoxResult Show(string messageBoxText, string caption)                                                                                                
static System.Windows.MessageBoxResult Show(string messageBoxText)                                                                                                                
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText, string caption, System.Windows.MessageBoxButton button,                           
System.Windows.MessageBoxImage icon, System.Windows.MessageBoxResult defaultResult, System.Windows.MessageBoxOptions options)                                                     
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText, string caption, System.Windows.MessageBoxButton button,                           
System.Windows.MessageBoxImage icon, System.Windows.MessageBoxResult defaultResult)                                                                                               
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText, string caption, System.Windows.MessageBoxButton button,                           
System.Windows.MessageBoxImage icon)                                                                                                                                              
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText, string caption, System.Windows.MessageBoxButton button)                           
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText, string caption)                                                                   
static System.Windows.MessageBoxResult Show(System.Windows.Window owner, string messageBoxText)       

 

Don’t let the overload definitions overwhelm you—once again, they simply show different ways to call Show() to make your life easier.

 

Identifying Valid Options

What’s much more important is identifying the true type names for the arguments. In the example above, we submitted strings and let PowerShell automatically convert them into the appropriate types.

For example, we passed the string "Question" for the argument System.Windows.MessageBoxImage icon. As you know from the previous parts, the message box icon is supposed to be of type System.Windows.MessageBoxImage, not a string. We got away with using "Question" because this string can be converted to System.Windows.MessageBoxImage:

 


PS C:\> 'Question' -as [System.Windows.MessageBoxImage]
Question

 

The correct approach would have been to pass the System.Windows.MessageBoxImage type directly, like this:


[System.Windows.MessageBoxImage]::Question 

This way, your PowerShell editor and its IntelliSense would have displayed all the other valid icon options. As explained in the previous parts, you can always list these options using Get-Member:


PS C:\> [System.Windows.MessageBoxImage] | Get-Member -Static


   TypeName: System.Windows.MessageBoxImage

Name              MemberType Definition                                                                                                                                           
----              ---------- ----------                                                                                                                                           
Equals            Method     static bool Equals(System.Object objA, System.Object objB)                                                                                           
Format            Method     static string Format(type enumType, System.Object value, string format)                                                                              
GetName           Method     static string GetName(type enumType, System.Object value)                                                                                            
GetNames          Method     static string[] GetNames(type enumType)                                                                                                              
GetUnderlyingType Method     static type GetUnderlyingType(type enumType)                                                                                                         
GetValues         Method     static array GetValues(type enumType)                                                                                                                
IsDefined         Method     static bool IsDefined(type enumType, System.Object value)                                                                                            
Parse             Method     static System.Object Parse(type enumType, string value), static System.Object Parse(type enumType, string value, bool ignoreCase)                    
ReferenceEquals   Method     static bool ReferenceEquals(System.Object objA, System.Object objB)                                                                                  
ToObject          Method     static System.Object ToObject(type enumType, System.Object value), static System.Object ToObject(type enumType, sbyte value), static System.Object...
TryParse          Method     static bool TryParse[TEnum](string value, [ref] TEnum result), static bool TryParse[TEnum](string value, bool ignoreCase, [ref] TEnum result)        
Asterisk          Property   static System.Windows.MessageBoxImage Asterisk {get;}                                                                                                
Error             Property   static System.Windows.MessageBoxImage Error {get;}                                                                                                   
Exclamation       Property   static System.Windows.MessageBoxImage Exclamation {get;}                                                                                             
Hand              Property   static System.Windows.MessageBoxImage Hand {get;}                                                                                                    
Information       Property   static System.Windows.MessageBoxImage Information {get;}                                                                                             
None              Property   static System.Windows.MessageBoxImage None {get;}                                                                                                    
Question          Property   static System.Windows.MessageBoxImage Question {get;}                                                                                                
Stop              Property   static System.Windows.MessageBoxImage Stop {get;}                                                                                                    
Warning           Property   static System.Windows.MessageBoxImage Warning {get;} 


 

Using Appropriate Types

Here is the example script from above, this time using the correct types instead of strings:


# loading the required .NET type
Add-Type -AssemblyName PresentationFramework

$Caption = 'Attention'
$Message = "I need to restart your server`r`n`r`nMay I proceed?"
$Buttons = [System.Windows.MessageBoxButton]::'YesNo'
$Icon = [System.Windows.MessageBoxImage]::Question

[System.Windows.MessageBoxResult]$result = [System.Windows.MessageBox]::Show($Message, $Caption, $Buttons, $Icon)

if ($result -eq [System.Windows.MessageBoxResult]::Yes)
{
  Write-Warning 'I am restarting...'
}
else
{
  Write-Warning 'Ok, I am aborting...' 
}

This code is much easier to edit in your PowerShell editor because you can now easily see the available options for dialog buttons and icons.

Cmdlets and .NET

In part 1, we explored the relationship between PowerShell cmdlets and .NET types. By now, you’ve seen that most cmdlets internally utilize existing .NET types and that you can call .NET types directly as well.

Now, we’ve reached the perfect point to illustrate why cmdlets exist and why using .NET methods directly isn’t always the best choice. The message box dialog works well but requires dealing with fairly complex code and unfamiliar types.

Let’s wrap a cmdlet around this code and see what happens. Of course, instead of a binary cmdlet wrapper, we’ll use a PowerShell function:


#region reusable code
Add-Type -AssemblyName PresentationFramework

function Show-MessageBox
{
  param
  (
    [Parameter(Mandatory)]
    [string]
    $Message,
    
    [string]
    $Caption = 'Attention',
    
    [System.Windows.MessageBoxButton]
    $Buttons = [System.Windows.MessageBoxButton]::'YesNo',
    
    [System.Windows.MessageBoxImage]
    $Icon = [System.Windows.MessageBoxImage]::Question
  )

  return [System.Windows.MessageBox]::Show($Message, $Caption, $Buttons, $Icon)
}
#endregion reusable code

$result = Show-MessageBox -Message "I need to restart your server`r`n`r`nMay I proceed?"

if ($result -eq [System.Windows.MessageBoxResult]::Yes)
{
  Write-Warning 'I am restarting...'
}
else
{
  Write-Warning 'Ok, I am aborting...'
} 

 

In the code region "reusable code," the new function Show-MessageBox is defined. It specifies the parameters with the correct types that the underlying .NET method requires.

In your script, you can now simply call Show-MessageBox whenever you need a dialog. What’s even better is that when you use parameters like -Buttons or -Icon, your PowerShell editor will display an IntelliSense list showing all the available options.

This is how most cmdlets work: they encapsulate complex .NET code so you can call a simple command. They define parameters using the exact types required by .NET, which provides you with convenient IntelliSense options.

 

Wrap Up

Our little journey illustrated that knowing .NET types (and how to directly call their methods) provides a lot of additional control. It is perfectly fine to directly call .NET types provided (a) there is no cmdlet for the same purpose already, and (b) calling .NET directly does not involve complex types and code.

If it does, as in the last example with the message box, you now understand why cmdlets exist: they are not in competition with .NET. Instead, they are a great way to simplify the user experience when .NET becomes too complex.

 

Good2know

Your ultimate PowerShell Cheat Sheet

Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.

The poster is available for download and in paper form.

PowerShell Poster 2023

Get your poster here!

 

 

Related links 

 

Related posts

4 min read

Bulk Testing PowerShell Scripts with the Tokenizer

In Part 1, we explored the internal PowerShell parser to see how it analyzes code and breaks it down into individual...

3 min read

Mastering PowerShell Tokenization for Efficient Scripting

The internal PowerShell parser processes any code before execution. With full access to this parser, you can analyze...

3 min read

Using .NET Libraries in PowerShell - Functions, Cmdlets and .NET

In part 3, we identified a useful .NET method to display system dialogs and then wrapped it inside a new PowerShell...

About the author: