Building a PowerShell GUI (Part 7)

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

In my previous article, I showed you how to configure the PowerShell GUI to display a virtual machine name. The script and its output weren’t exactly impressive, but they demonstrated the fact that it is possible to display something other than static text within a PowerShell GUI. My goal in this article, is to show you how you can gain better control over the text that is displayed.

As you looked at the output from my script, you might have found it curious that although I retrieved a list of all of the virtual machines on a Hyper-V server, I only displayed one virtual machine name. The reason why I did this was to illustrate the point that sometimes you have to be a little bit creative when it comes to displaying output within a GUI. Labels aren’t always the best choice for displaying text.

In this particular case, labels work fine. The lab server on which my script is running only contains about nine or ten virtual machines, and I can easily display those virtual machine names within a label. The trick is formatting the text so that it displays correctly. Here is my revised DisplayVMs function:

#Define Button Click Function

Function DisplayVMs

{

$VirtualMachines = Get-VM

Add-Type -AssemblyName System.Windows.Forms

#Create text

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

$Label.AutoSize = $True

ForEach ($vm in $VirtualMachines){

$NL = “`n”

$Label.Text = $Label.Text + $VM.Name + $NL

}

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

$Form.Controls.Add($Label)

}

The first several lines of code haven’t changed. However, you will notice that there is a line of text that sets auto size to true. The label’s auto size has to be set to true. Otherwise, the output is limited to two lines of text. It is also worth noting that I moved the AutoSize line further up in the function so that it occurs before I assign any label text.

Another thing that I did was to create a ForEach loop. This loop allows me to work through the array (list) of virtual machines, and list each virtual machine one by one. So for each virtual machine ($vm) in the list of virtual machines ($VirtualMachines), I am appending the virtual machine name ($VM.Name) to the label ($Label.Text).

You will also notice that I have created a variable called $NL and am appending the contents of this variable to the virtual machine name. The $NL variable is used to insert a line feed. That way, each virtual machine is listed on a new line. The variable itself contains the text: `n. This is the PowerShell “new line” code. When using this code, be careful to use the correct character. The ` symbol is not an apostrophe. It is the symbol that shares a keyboard key with the ~ symbol.

So with that said, Figure A shows what the output looks like after I click the button.

Image
Figure A: I am displaying the full list of virtual machines.

OK, the output accomplished what I needed it to, but let’s clean things up a bit. Let’s add a block of text telling whoever is using the script what will happen when they click the button. Let’s also move the button and the output text, and let’s call the button something other than Button. Finally, let’s change the window name to something other than Hello World.

This sounds like a lot of work, but it is actually pretty simple to do. Let’s start with adding a second block of text. To do so, I created a variable called $Label2 and then used a line of code ($Form.Controls.Add($Label2)) to display the label. The label itself was created using four lines of code that are very similar to those used for label1, except that they display static text. Here are those few lines of code:

# Create Label2

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

$Label2.AutoSize = $True

$Label2.Location = new-object System.Drawing.Size(20,50)

$Label2.Text = “Click the button to see a list of the virtual machines hosted on the server.”

As you look at the block of code above, you will notice a line that starts with $Label2.Location. The numbers that are used at the end of this line are X / Y coordinates that determine where the label text will be displayed within the dialog box. In this case, the text is being displayed 20 pixels to the right and 50 pixels down from the dialog box’s upper left corner. I used nearly identical lines of code to move the $Label1 text and the button.

Incidentally, changing the name of the button and changing the name of the window were a matter of replacing static text. The button name is controlled by the $Button1.Text variable, and the window name is controlled by the $Form.Text variable.

Here is the full script:

#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 Button Click Function

Function DisplayVMs

{

$VirtualMachines = Get-VM

Add-Type -AssemblyName System.Windows.Forms

#Create text

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

$Label.AutoSize = $True

Foreach ($vm in $VirtualMachines){

$NL = “`n”

$Label.Text = $Label.Text + $VM.Name + $NL

}

 

$Label.Location = new-object System.Drawing.Size(200,110)

$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 = “Hyper-V Virtual Machines”

$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 Label2

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

$Label2.AutoSize = $True

$Label2.Location = new-object System.Drawing.Size(20,50)

$Label2.Text = “Click the button to see a list of the virtual machines hosted on the server.”

 

#Create button

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

$Button1.Location = new-object System.Drawing.Size(30,70)

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

$Button1.Text = “OK”

$Button1.Add_Click({DisplayVMs})

 

#Create the Form

$Form.Controls.Add($Button1)

$Form.Controls.Add($Label2)

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

$Form.ShowDialog()

Here is the output from the revised script, following a button click.

Image
Figure B: The script’s output has been cleaned up.

Conclusion

There are a few points that I hope that you will take away from this article. First, you can add multiple elements to a window. In this case, I am using two labels, but I could have just as easily created multiple buttons using the same technique.

A second takeaway is that within a PowerShell GUI, each element’s position is controlled individually via X / Y coordinates. You can move buttons, labels, and other objects to any position you like, just by changing the coordinates.

Finally, labels can be used to display multiple lines of text, but they do have their limits. Sometimes you may need to use a text box instead of a label.

Now that you know the basics of creating a PowerShell GUI, I want to show you how to add a bit of visual flare. In the next article, I will show you how to add some color and then I will show you some other visual elements that you can add.

1 thought on “Building a PowerShell GUI (Part 7)”

Leave a Comment

Your email address will not be published. Required fields are marked *

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

Scroll to Top