Saturday, September 16, 2006 5:24 AM bart

Using System.Windows.Forms.MessageBox in PowerShell

PowerShell fans will have seen numerous examples using the get-process and stop-process cmdlets. Combine it with the power of -confirm and every normal self-respecting IT admin should feel a good amount of adrenaline flowing through their veins.

Consider the following:

gps [a-c]* | where something } | stop-process

The part indicated in red is just a plain script block that has to return a boolean value, telling PowerShell whether or not to pass the object that flows through the pipeline from the left to right. That is, if gps [a-c]* returns:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    125       4    13864      10920    47            1240 audiodg
     30       2      780       3392    34     0,06   4124 conime
    551       5     1636       4444    85             564 csrss
    518       7     2052      11480   156             628 csrss

all of these four System.Diagnostic.Process instances will flow through the pipeline one-by-one on to the where cmdlet, that's asking just one simple question "Pass this System.Diagnostics.Process object through or not?" by evaluation the script block. Inside the script block one can use the variable $_ that represents the current object flowing through the pipeline:

where { $false } won't pass through anything
where { $true  } will pass through anything
where { $_.ProcessName -eq "notepad" } will evaluate the condition
where { $s = $_.ProcessName; $s -eq "notepad" } will evaluate the condition using some temporary variable

Get the point? Now, what about asking the end-user using - how do you guess - a MessageBox? Let's start by trying to display a simple MessageBox on the screen, outside the where-stuff:

PS C:\Users\Bart> [System.Windows.Forms.MessageBox]::Show("Hello")
Unable to find type [System.Windows.Forms.MessageBox]: make sure that the assembly containing this type is loaded.
At line:1 char:34
+ [System.Windows.Forms.MessageBox]: <<<< :Show("Hello")

PS C:\Users\Bart>

Whoops! Don't worry. As developers have to add a reference to an assembly to their projects, you have to do a similar thing in PowerShell. A straightforward way to get around this is this:

PS C:\Users\Bart> [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System.Windows.Forms\2.0....

Now try to display the MessageBox again. This is what you get to see now:

Now revisit the scene of the where cmdlet (i.e. Where-Object) and consider the following piece of code:

PS C:\Users\Bart> gps [a-c]* | where {
>> $s = "Select " + $_.ProcessName + "?";
>> $d = [Windows.Forms.MessageBox]::Show($s, "PowerShell rocks", [Windows.Forms.
MessageBoxButtons]::YesNo, [Windows.Forms.MessageBoxIcon]::Question)
>> $d -eq [Windows.Forms.DialogResult]::Yes
>> }
>>

Don't worry, this code isn't difficult at all. The first two lines are straightforward if you have some basic knowledge of System.Windows.Forms and the use of variables in PowerShell. Notice the use of square brackets to specify a class name and the :: operator to call a static method. The last one is the one that evaluates the boolean condition based on a comparison of the dialog result with the DialogResult.Yes enumerator value: $d -eq [Windows.Forms.DialogResult]::Yes

The system will now present a MessageBox dialog for audiodg, conime, csrss and csrss, as shown below. Depending on the answer you choose, you'll see the list of passed objects grow in the background in the PowerShell window:

Useful or not? Maybe in some scenarios where the black-n-white command line environment doesn't feel comfortable enough for system "operators". It's just a matter of taste I guess. Nevertheless, this little sample shows you some key concepts:

  • How the Windows PowerShell pipeline works.
  • How to reference an assembly in Windows PowerShell.
  • How the Where-Object cmdlet (aliased as "where") works.
  • The omnipresence of .NET in the world of Windows PowerShell.

I'd say: "Dive deeper in the blue PS ocean". Cheers!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# re: Using System.Windows.Forms.MessageBox in PowerShell

Saturday, September 16, 2006 9:06 PM by /\/\o\/\/

Very cool example of using the where Cmdlet !

Greetings /\/\o\/\/

# re: Using System.Windows.Forms.MessageBox in PowerShell

Saturday, September 16, 2006 10:48 PM by Karl Prosser

this is a cool insight and technique.. sure it does seem redundant when there is the -confirm switch however there are commadnlets that don't support confirm, and functions, dotnet methods that don't even and can't support confirm (i.e lets say there was no cmdlet such as stop-process, and you had to do $_.kill() then your technique would be great.. maybe a cool function or cmdlet, would be wrapping up this functionality into a function or cmdlet, which takes in a parameter which is a scriptblock that generates the text for the messagebox, and filters the pipeline accordingly.
i.e (this is psuedo code, i didn't go check that the parameter names were correct

gps | confirm-messagebox { "do you really want to stop $_.processname } | foreach { $_.kill() }

# re: Using System.Windows.Forms.MessageBox in PowerShell

Sunday, September 17, 2006 7:27 AM by Lee

This is really great, Bart.

I especially like the way that you dealt with the topic in such a clear tutorial fashion.

# &amp;amp;quot;Windows Powershell in action&amp;amp;quot;

Tuesday, September 19, 2006 12:07 AM by [MSFT-BE] Arlindo's Blog - IT Pro Evangelist

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; I am currently reading the first chapters of a Powershell...

# re: Using System.Windows.Forms.MessageBox in PowerShell

Saturday, September 30, 2006 9:14 AM by Rick

The stealthy nature of the dialog box without focus had me stumped for a while :)

i.e. under XP Pro the MessageBox pops up in the background and the script (which still has focus) "hangs" waiting....

It was a Duh moment for me :)


# A graphical MessageBox confirmation cmdlet in PowerShell

Thursday, October 05, 2006 12:32 PM by B# .NET Blog

Introduction
I've been posting about Windows PowerShell programmability quite a bit lately. A few interesting...

# &amp;quot;Windows Powershell in action&amp;quot;

Wednesday, October 18, 2006 2:07 PM by [MSFT-BE] Arlindo's Blog - IT Pro Evangelist

I am currently reading the first chapters of a Powershell book called &quot;Windows Powershell in Action&quot;

# Windows call .Net CLR in PowerShell script - Oracle ABC Wiki

Pingback from  Windows call .Net CLR in PowerShell script - Oracle ABC Wiki