Building a PowerShell GUI (Part 11)

by [Published on 1 Dec. 2016 / Last Updated on 1 Dec. 2016]

I have two goals for this article. My primary goal is to modify the code we've created so far so that it displays some basic configuration information for the selected virtual machine. My secondary goal is to show you a couple of new techniques for displaying the script’s output.

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

In my previous article, I spent quite a bit of time cleaning up my code to make it flow in a more logical manner. As it stands now, the code allows the user to pick a virtual machine from a list of the virtual machines residing on the server, and then it simply outputs the name of the selected virtual machine. The output looks pretty, but it doesn’t really do anything useful.

I have actually used one of these techniques already, but I want to build on it. As you may recall, I have thus far been displaying text as a label. In fact, the script defines a separate label for each line of text that will be displayed. Here is an example:

# Define Label2 - The Please Make a Selection Text
$Label2 = New-Object System.Windows.Forms.Label
$Label2.AutoSize = $True
$Label2.Location = new-object System.Drawing.Size(20,50)
$Label2.ForeColor = "DarkBlue"
$Label2.Text = "Please select a virtual machine from the list."

As you can see, this block of code sets the basic attributes for the label. I used this particular approach because we have to define not only the label text, but also the location where the label will be displayed. Now you may be wondering why I have chosen to create a separate label for each line of text, rather than creating a single label and passing the text string to the label as a variable. This is actually a somewhat complicated question to answer, because there are two seemingly contradictory answers.

The first answer is that you can pass text to a variable and then assign that variable to a label. In fact, I have already done it. Remember that my script allows you to pick a virtual machine from a list, and then displays the name of the chosen virtual machine. In order to do this, I had to put the virtual machine name into a variable, and then assign that variable to a label. As you can see in the block of code below, I populated the label text just before displaying the label:

$Label.Text = $ChosenItem
$Form.Controls.Add($Label)

I am going to be using this same technique to display virtual machine attributes, because those attributes do not exist as static text.

The other part of the answer to why I’m not just using a single label is because I can’t. Remember that a label is an object that we place onto the screen. When we clear the screen, we actually have to instruct PowerShell to remove the object. Hence, we can modify a label’s text, but we can’t use a single label to display a number of different independent blocks of text on the screen simultaneously.

So let’s get back to the topic at hand. In order to adapt my script to display virtual machine information, I had to make several changes. The first change that I made was to the $Label object. That object was originally a text box, but I changed it to a standard label. Certainly I could have displayed virtual machine information in a text box, but my plan is to eventually make the script more interactive, and this change lays the groundwork for what I will be doing later on.

The next thing that I did was to create several additional labels that will serve to display virtual machine attributes. Of course I also had to add code to display the labels, and I had to modify my code that clears the screen so that it would remove the new labels.

For the most part the new labels are just like the old ones. The only thing that I am doing different is turning AutoSize off, manually setting a label size, and then setting the text color to black and the background color to white. I did this purely for aesthetics. Remember that before, the script’s output was displayed within a text box. Since the text box no longer exists, I am basically creating a fake text box by making all of the labels the same size and color. Here is a sample of the new label code:

# Define Label4 - The This is the VM State label
$Label4 = New-Object System.Windows.Forms.Label
$Label4.AutoSize = $False
$Label4.Location = new-object System.Drawing.Size(50,70)
$Label4.Size = New-Object System.Drawing.Size(200,20)
$Label4.ForeColor = "Black"
$Label4.BackColor = 'White'

Once the basic label structure was in place, displaying VM information became easy. As you may recall, I have a variable named $ChosenItem that contains the virtual machine name. I therefore created another variable called $SelectedVM that stores all of the attributes associated with the specified VM by using the Get-VM command. I then set up a number of other variables to store individual VM attributes, and then added those variables to label text. Here is what the block of code looks like:

# Get Virtual Machine Information
 
$SelectedVM = Get-VM $ChosenItem
$Name = $SelectedVM.VMName
$State = $SelectedVM.State
$RunTime = $SelectedVM.UpTime
$Memory = $SelectedVM.MemoryAssigned
$CPU = $SelectedVM.ProcessorCount
 
#Create text
$Label.Text = 'Virtual Machine Name: ' + $Name
$Label4.Text = 'VM State: ' + $State
$Label5.Text = 'VM Up Time: ' + $RunTime
$Label6.Text = 'Memory Assigned: ' + $Memory
$Label7.Text = 'Virtual CPUs Assigned :' + $CPU
 
#Display Text
$Form.Controls.Add($Label)
$Form.Controls.Add($Label4)
$Form.Controls.Add($Label5)
$Form.Controls.Add($Label6)
$Form.Controls.Add($Label7)
$Form.Controls.Add($Label3)
$Form.Controls.Add($Button3)
$Form.Controls.Add($Button4)
}

Now, when I run the script and select a virtual machine, the script displays VM information. You can see what the output looks like in the figure below:

Image
The output now displays VM information.

Here is the code in its entirety:

#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
 
# Display the Main Screen
Function Display-MainScreen
{
$Form.Controls.Add($ListBox1)
$Form.Controls.Add($Button1)
$Form.Controls.Add($Button2)
$Form.Controls.Add($Label2)
}
 
# ---------- Button Click Actions ------
 
#Define Return Button Click Function
Function Return-MainScreen
{
 
$Form.Controls.Remove($Label)
$Form.Controls.Remove($Label3)
$Form.Controls.Remove($Label4)
$Form.Controls.Remove($Label5)
$Form.Controls.Remove($Label6)
$Form.Controls.Remove($Label7)
$Form.Controls.Remove($Button3)
$Form.Controls.Remove($Button4)
$Form.Refresh()
Display-MainScreen
}
 
#Define OK Button Click Function
Function Display-VMInfo($ChosenItem)
{
 
#Clear the window
$Form.Controls.Remove($ListBox1)
$Form.Controls.Remove($Label2)
$Form.Controls.Remove($Button1)
$Form.Controls.Remove($Button2)
$Form.Refresh()
 
#Create Output
Add-Type -AssemblyName System.Windows.Forms
 
# Get Virtual Machine Information
 
$SelectedVM = Get-VM $ChosenItem
$Name = $SelectedVM.VMName
$State = $SelectedVM.State
$RunTime = $SelectedVM.UpTime
$Memory = $SelectedVM.MemoryAssigned
$CPU = $SelectedVM.ProcessorCount
 
#Create text
$Label.Text = 'Virtual Machine Name: ' + $Name
$Label4.Text = 'VM State: ' + $State
$Label5.Text = 'VM Up Time: ' + $RunTime
$Label6.Text = 'Memory Assigned: ' + $Memory
$Label7.Text = 'Virtual CPUs Assigned :' + $CPU
 
#Display Text
$Form.Controls.Add($Label)
$Form.Controls.Add($Label4)
$Form.Controls.Add($Label5)
$Form.Controls.Add($Label6)
$Form.Controls.Add($Label7)
$Form.Controls.Add($Label3)
$Form.Controls.Add($Button3)
$Form.Controls.Add($Button4)
}
 
#------ Define All GUI Objects-------
 
# Define Label - This is a text box object that will display VM data
$Label = New-Object System.Windows.Forms.Label
$Label.AutoSize = $False
$Label.Location = new-object System.Drawing.Size(50,50)
$Label.Size = New-Object System.Drawing.Size(200,20)
$Label.ForeColor = "Black"
$label.BackColor = 'White'
 
# Define Label2 - The Please Make a Selection Text
$Label2 = New-Object System.Windows.Forms.Label
$Label2.AutoSize = $True
$Label2.Location = new-object System.Drawing.Size(20,50)
$Label2.ForeColor = "DarkBlue"
$Label2.Text = "Please select a virtual machine from the list."
 
# Define Label3 - The This is Your Selected Virtual Machine Text
$Label3 = New-Object System.Windows.Forms.Label
$Label3.AutoSize = $True
$Label3.Location = new-object System.Drawing.Size(50,30)
$Label3.ForeColor = "DarkBlue"
$Label3.Text = "Your selected virtual machine:"
 
# Define Label4 - The This is the VM State label
$Label4 = New-Object System.Windows.Forms.Label
$Label4.AutoSize = $False
$Label4.Location = new-object System.Drawing.Size(50,70)
$Label4.Size = New-Object System.Drawing.Size(200,20)
$Label4.ForeColor = "Black"
$Label4.BackColor = 'White'
 
# Define Label5 - The This is the VM State label
$Label5 = New-Object System.Windows.Forms.Label
$Label5.AutoSize = $False
$Label5.Location = new-object System.Drawing.Size(50,90)
$Label5.Size = New-Object System.Drawing.Size(200,20)
$Label5.ForeColor = "Black"
$Label5.BackColor = "White"
 
# Define Label6 - The This is the VM State label
$Label6 = New-Object System.Windows.Forms.Label
$Label6.AutoSize = $False
$Label6.Location = new-object System.Drawing.Size(50,110)
$Label6.Size = New-Object System.Drawing.Size(200,20)
$Label6.ForeColor = "Black"
$Label6.BackColor = 'White'
 
# Define Label7 - The This is the VM State label
$Label7 = New-Object System.Windows.Forms.Label
$Label7.AutoSize = $False
$Label7.Location = new-object System.Drawing.Size(50,130)
$Label7.Size = New-Object System.Drawing.Size(200,20)
$Label7.ForeColor = "Black"
$Label7.BackColor = 'White'
 
# Define List Box - This will display the virtual machines that can be selected
$ListBox1 = New-Object System.Windows.Forms.ListBox
$ListBox1.Location = New-Object System.Drawing.Size(20,80)
$ListBox1.Size = New-Object System.Drawing.Size(260,20)
$ListBox1.Height = 80
 
                # This code populates the list box with virtual machine names
                $VirtualMachines = Get-VM
                ForEach ($VM in $VirtualMachines)
                                {
                                [void] $ListBox1.Items.Add($VM.Name)
                                }
 
 
# Define Button 1  - This is the selection screen's OK button
$Button1 = new-object System.Windows.Forms.Button
$Button1.Location = new-object System.Drawing.Size(20,170)
$Button1.Size = new-object System.Drawing.Size(70,30)
$Button1.BackColor ="LightGray"
$Button1.Text = "OK"
$Button1.Add_Click({$ChosenItem=$ListBox1.SelectedItem;Display-VMInfo $ChosenItem})
 
 
# Define Button 2 - This is the selection screen's Cancel button
$Button2 = New-Object System.Windows.Forms.Button
$Button2.Location = New-Object System.Drawing.Size(120,170)
$Button2.Size = New-Object System.Drawing.Size(70,30)
$Button2.BackColor ="LightGray"
$Button2.Text = "Cancel"
$Button2.Add_Click({$Form.Close()})
 
 
# Define Button 3 - This is the Return to Main Screen button
$Button3 = New-Object System.Windows.Forms.Button
$Button3.Location = New-Object System.Drawing.Size(50,220)
$Button3.Size = New-Object System.Drawing.Size(70,30)
$Button3.BackColor ="LightGray"
$Button3.Text = "Return"
$Button3.Add_Click({Return-MainScreen})
 
 
# Define Button 4 - This button doesn't do anything yet, but we will use it eventually.
$Button4 = New-Object System.Windows.Forms.Button
$Button4.Location = New-Object System.Drawing.Size(140,220)
$Button4.Size = New-Object System.Drawing.Size(150,30)
$Button4.BackColor ="LightGray"
$Button4.Text = "Reserved for Future Use"
$Button4.Add_Click({$Form.Close()})
 
# -------- This is the end of the object definition section ------
 
 
 
# -----Draw the empty form----
$Form = New-Object System.Windows.Forms.Form
$Form.width = 525
$Form.height = 350
$Form.BackColor = "lightblue"
$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()}})
 
#----Populate the form----
Display-MainScreen
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()

Now that the script displays useful information, I want to make it more interactive. My goal is to modify the script so that you can use it to start and stop the VM, and make changes to the amount of memory that is assigned to the VM.

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

See Also


The Author — Brien M. Posey

Brien M. Posey avatar

Brien Posey is an MCSE and has won the Microsoft MVP award for the last few years. Brien has written well over 4,000 technical articles and written or contributed material to 27 books.

Advertisement

Featured Links