Pages

Saturday, February 14, 2015

GUIs in PowerShell

I've been teasing about PowerShell GUIs for a while now, but I've been swamped at work.

When we want to make PowerShell GUIs, we have two options, Windows Forms (WinForms) and Windows Presentation Framework (WPF). I've written both, but I prefer WinForms as I've seen issues where some WPF elements are not compatible with PowerShell v2 (DataGrid comes to mind). Yeah, yeah... Who cares? But the reality is that v2 is still out there. Actually, the problem wasn't PowerShell v2, it was the fact that v2 doesn't use .NET 4 out of the box. It can be made to use .NET 4, but I wasn't a huge fan of that approach.

When working with GUIs (whether WinForms or WPF), you have to "build" the GUI in code. This can be very cumbersome and involve a lot of trial and error when trying to get elements to line up just how you want them. Luckily, there are some ISEs out there with form builders. Some are free, some are not. I'm old fashioned and don't use an ISE normally (I still use good ole notepad), but for GUIs, I have to make an exception for the form building. I know, I really should embrace ISE and use them more. The syntax highlighting and Intellisense is great, but I just can't pull myself away from using notepad. :-)

Being cheap, I chose to try a lot of the free ones, and I liked Admin Script Editor the best. The form builder, reminds me a lot of Visual Studio. It also is the best way that I've found to compile your PowerShell scripts into EXEs. Admin Script Editor is free and can be downloaded here.  I encourage you to try a few of them and make your own opinion.

OK, enough small chat, lets jump right into it. Today we are going to use Admin Script Editor to build a simple GUI with a button and a textbox. Once you start Admin Script Editor and create a new PowerShell Script, you can access the form builder from Tools -> ScriptForm Designer... The form designer looks like this:

We'll add a button and a textbox. We'll modify the properties like so:
Form Name: frmMain
Form Text: Sample GUI
Button Name: butClickMe
Button Text: Click Me
Textbox Name: txtTextbox



Now we go to File -> Save to ASE and the form code will be added to Admin Script Editor.


If you run the script, the GUI will be displayed, but obviously, the button doesn't do anything when you click it. Next we'll add an event handler for the button click event. Admin Script Editor adds a region called Event Handlers.  Make sure that all your code is above the call to Main.

We'll add a handler to handle the Click event.
$butClickMe.Add_Click({
     $txtTextbox.Text = "Hello World"
})

Now when you run the script and click the button, the textbox will display "Hello World".

And there ya have it.  A simple GUI written in PowerShell.

When I'm building WinForms, I tend to rely heavily on MSDN for reference.  It's a very useful resource.

The whole source is below:
#region ScriptForm Designer

#region Constructor

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

#endregion

#region Post-Constructor Custom Code

#endregion

#region Form Creation
#Warning: It is recommended that changes inside this region be handled using the ScriptForm Designer.
#When working with the ScriptForm designer this region and any changes within may be overwritten.
#~~< frmMain >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$frmMain = New-Object System.Windows.Forms.Form
$frmMain.ClientSize = New-Object System.Drawing.Size(278, 138)
$frmMain.Text = "Sample GUI"
#~~< txtTextbox >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$txtTextbox = New-Object System.Windows.Forms.TextBox
$txtTextbox.Location = New-Object System.Drawing.Point(47, 65)
$txtTextbox.Size = New-Object System.Drawing.Size(183, 20)
$txtTextbox.TabIndex = 1
$txtTextbox.Text = ""
#~~< butClickMe >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$butClickMe = New-Object System.Windows.Forms.Button
$butClickMe.Location = New-Object System.Drawing.Point(98, 22)
$butClickMe.Size = New-Object System.Drawing.Size(75, 23)
$butClickMe.TabIndex = 0
$butClickMe.Text = "Click Me"
$butClickMe.UseVisualStyleBackColor = $true
$frmMain.Controls.Add($txtTextbox)
$frmMain.Controls.Add($butClickMe)

#endregion

#region Custom Code

#endregion

#region Event Loop

function Main{
     [System.Windows.Forms.Application]::EnableVisualStyles()
     [System.Windows.Forms.Application]::Run($frmMain)
}

#endregion

#endregion

#region Event Handlers

$butClickMe.Add_Click({
     $txtTextbox.Text = "Hello World"
})

Main #This call must remain below all other event functions

#endregion

Questions or suggestions?  Leave a comment.  You can also follow me on Facebook.  Happy Scripting!

1 comment:

  1. "Happy Valentine's Day sweetie! Look I made a blog post in your honor...it's about GUIs in PowerShell!"

    ReplyDelete