Building a PowerShell GUI (Part 4)

If you would like to read the other parts in this article series please go to:

So far in this article series, I have shown you how to create a GUI based, Hello World script in PowerShell. I then went back and added some color and some other nice visual elements. My original intent for this article was to begin building a GUI for a “real” PowerShell script. While this article does start that process, I want to take a big step back and approach the GUI creation process in a completely different way. The reason why I am doing this is because, I believe that this method is going to benefit more people than my previous method.

As you will recall, my previous GUI creation method involved using Visual Studio to create XAML code and then referencing that code from PowerShell. This particular method works really well. The reason why I had initially chosen to use that method is because I love being able to use Visual Studio to draw the script’s GUI interface rather than having to code the entire GUI manually. Even so, the XAML method does have its drawbacks. Some of the disadvantages include:

  • My previous method required the use of Visual Studio, which typically incurs licensing costs.
  • The XAML code must be kept separate from the PowerShell code. This results in dependencies being created, and the PowerShell script will never be self-contained.
  • XAML code does not follow the same syntax as native PowerShell code.

Because of these drawbacks, I wanted to show you how you could recreate our Hello World script using native PowerShell. In doing so, I am going to structure the code in a way that will allow us to begin building a “real script” much more easily.

So with that said, here is what the original Hello World script looked like. This is the script from Part 2 of this series, before I added color.

#Required to load the XAML form and create the PowerShell Variables

./LoadDialog.ps1 -XamlPath ‘C:\Forms\MyForm.xaml’

 

#EVENT Handler

$MyButton.add_Click({

$MyLabel.Content = “Hello World”

})

 

#Launch the window

$xamGUI.ShowDialog() | out-null

The code is super short, and would be even shorter if we omitted the comment lines. The reason why the code is so short is because we did almost everything in XAML. You can see the XAML code here:

<Window

xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

Title=”MainWindow” Height=”350″ Width=”525″>

<Grid>

<Button Name=”MyButton” Content=”Button” HorizontalAlignment=”Left” Margin=”249,132,0,0″ VerticalAlignment=”Top” Width=”75″/>

<Label Name=”MyLabel” Content=”Label” HorizontalAlignment=”Left” Margin=”88,73,0,0″ VerticalAlignment=”Top”/>

 

</Grid>

</Window>

When executed, this script produced the output shown in Figure A.

Image
Figure A: This is the output from the XAML-based code.

Now, let’s take a look at how to write the exact same program using only native PowerShell. Here is the code:

#Load Assemblies

[System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”) | Out-Null

[System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”) | Out-Null

$net = New-Object -ComObject Wscript.Network

 

#Define Butten Click Function

Function DisplayHelloWorldText{

Add-Type -AssemblyName System.Windows.Forms

#Create Hello World text

$Label = New-Object System.Windows.Forms.Label

$Label.Text = “Hello World”

$Label.AutoSize = $True

$Label.Location = new-object System.Drawing.Size(88,73)

$Form.Controls.Add($Label)

}

 

#Draw form

$Form = New-Object System.Windows.Forms.Form

$Form.width = 525

$Form.height = 350

$Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D

$Form.Text = “Hello World”

$Form.maximumsize = New-Object System.Drawing.Size(525,350)

$Form.startposition = “centerscreen”

$Form.KeyPreview = $True

$Form.Add_KeyDown({if ($_.KeyCode -eq “Enter”) {}})

$Form.Add_KeyDown({if ($_.KeyCode -eq “Escape”)

{$Form.Close()}})

 

#Create button

$Button1 = new-object System.Windows.Forms.Button

$Button1.Location = new-object System.Drawing.Size(249,132)

$Button1.Size = new-object System.Drawing.Size(80,20)

$Button1.Text = “Button”

$Button1.Add_Click({DisplayHelloWorldText})

 

 

#Create the Form

$Form.Controls.Add($Button1)

$Form.Add_Shown({$Form.Activate()})

$Form.ShowDialog()

You can see the code’s output in Figure B.

Image
Figure B:This is the output from the Hello World script written in Native PowerShell.

As you compare the two blocks of code and the two screen captures, there are a couple of key takeaways. First, the outputs are nearly identical to one another. Yes, there are slight differences in fonts and background colors, but those are things that are easy to change. The two scripts do exactly the same thing, and the button and the output are displayed in exactly the same positions in both programs. Even the window size is identical. The point is that native PowerShell can perfectly mimic anything that you might create using XAML. The downsides to using native PowerShell are that the code is lengthier, and you don’t get to use Visual Studio’s point and click interface to create the GUI.

The other important takeaway from the native PowerShell code is that when a user clicks on the button, the script is calling a PowerShell function. The fact that we can launch a function in response to a button press is going to make life vastly easier than if we were to try to develop a more complex script based around the use of XAML.

Admittedly, I did have to write a lot of code just to display a button on the screen and display the words Hello World in response to a button press. Even so, most of the code is relatively simple. The vast majority of the code that I have written is related to object size, positioning, and other visual formatting tasks. The core functionality is somewhat straightforward.

Before I try to step you through the code, I need to take a moment and introduce the technique that I am using. In order to build a PowerShell GUI, I have leveraged the power of PowerShell forms. You can think of a form as a window. By itself, a form is basically just a blank canvas (an empty window) within which you can add anything you want. A form can contain pictures, text, buttons, and a wide variety of controls.

You can build a form in three steps. The first step is to load the required assembly. Assemblies are part of the .NET framework. The idea behind using them is pretty simple. When you are writing a PowerShell script, you really don’t want to have to give Windows explicit instructions for drawing a window. Imagine if you had to code the minimize button, the drag and drop functionality, etc. Microsoft tries to save you time by providing you with a collection of building blocks called assemblies. These assemblies can be called from PowerShell and allow your script to use a pre-existing code library. These assemblies can save you a lot of work. In this case, the name of the assembly that we are loading is System.Windows.Forms.

The next thing that we have to do is to create a new form object. This can be done by using PowerShell’s New-Object cmdlet, and referencing the assembly that we loaded in the previous step.

The third step is to tell PowerShell to display the form. This requires a method called ShowDialog. A method is simply an object within a class. Our class in this case is System.Windows.Forms, and the method within the form that we are going to call is ShowDialog. A method is simply a block of code that performs a certain task. In this case, the method causes the form to be displayed.

Microsoft provides a really great sample, in which an empty window (form) is created using a three line PowerShell script. The three lines of code are:

Add-Type -AssemblyName System.Windows.Forms

$Form = New-Object system.Windows.Forms.Form

$Form.ShowDialog()

You can see the output from Microsoft’s code in Figure C.

Image
Figure C: PowerShell has created an empty window.

Conclusion

In this article, I have shown you how to write the Hello World script without the use of XAML. In the next article, I will step through my sample code. From there, we will begin building some GUI-based PowerShell applications.

Leave a Comment

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top