PowerShell GUI for your scripts. Episode 4

Check Boxes

Creating the check box:

$procName = New-Object System.Windows.Forms.checkbox #create the check box
$procName.Location = New-Object System.Drawing.Size(10,20) #location of the check box in relation to the group box's edges (length, height)
$procName.Size = New-Object System.Drawing.Size(100,20) #the size in px of the check box (length, height)
$procName.Checked = $true #check box is checked by default
$procName.Text = "Type" #labeling the check box
$groupBox.Controls.Add($procName) #activate the inside the group box

Note: I’ve added the check box object to a group box item as I did with the radio buttons in Episode 3. However, this is not quite as important since check boxes act independently of each other. Feel free to add it to the form instead if you prefer.

Creating the function:

function procInformation {

$wks = $DropDownBox.SelectedItem.ToString()

try {
$prcInfo = gwmi win32_processor -computer $wks -ErrorAction STOP

if ($procName.Checked -eq $true) {$Name = "Proc type: $($prcInfo.Name)"}
if ($procLoad.Checked -eq $true) {$Load = "Proc load: $($prcInfo.LoadPercentage) %"}
if ($procSpeed.Checked -eq $true) {$Freq = "Proc frequency: $($prcInfo.CurrentClockSpeed) MHz"}

$outputBox.text = "$Name `n$Load `n$Freq" 

       } #end try

catch {$outputBox.text = "`nOperation could not be completed"}

                           } # end procInformation

Note: you will notice I’ve added -ErrorAction STOP. I did this so gwmi errors become termination errors and can be handled by try/catch.

Full script:

Code here:

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

$Form = New-Object System.Windows.Forms.Form    
$Form.Size = New-Object System.Drawing.Size(600,400)  

############################################## Start functions

function procInformation {

$wks = $DropDownBox.SelectedItem.ToString()

try {
$prcInfo = gwmi win32_processor -computer $wks -ErrorAction STOP

if ($procName.Checked -eq $true) {$Name = "Proc type: $($prcInfo.Name)"}
if ($procLoad.Checked -eq $true) {$Load = "Proc load: $($prcInfo.LoadPercentage) %"}
if ($procSpeed.Checked -eq $true) {$Freq = "Proc frequency: $($prcInfo.CurrentClockSpeed) MHz"}

$outputBox.text = "$Name `n$Load `n$Freq" 

       } #end try

catch {$outputBox.text = "`nOperation could not be completed"}

                           } # end procInformation                  

############################################## end functions

############################################## Start group boxes

$groupBox = New-Object System.Windows.Forms.GroupBox
$groupBox.Location = New-Object System.Drawing.Size(250,20) 
$groupBox.size = New-Object System.Drawing.Size(130,100) 
$groupBox.text = "Processor Info:" 
$Form.Controls.Add($groupBox) 

############################################## end group boxes

############################################## Start check boxes

$procName = New-Object System.Windows.Forms.checkbox
$procName.Location = New-Object System.Drawing.Size(10,20)
$procName.Size = New-Object System.Drawing.Size(100,20)
$procName.Checked = $true
$procName.Text = "Type"
$groupBox.Controls.Add($procName)

$procLoad = New-Object System.Windows.Forms.checkbox
$procLoad.Location = New-Object System.Drawing.Size(10,40)
$procLoad.Size = New-Object System.Drawing.Size(100,20)
$procLoad.Text = "Load"
$groupBox.Controls.Add($procLoad)

$procSpeed = New-Object System.Windows.Forms.checkbox
$procSpeed.Location = New-Object System.Drawing.Size(10,60)
$procSpeed.Size = New-Object System.Drawing.Size(100,20)
$procSpeed.Text = "Frequency"
$groupBox.Controls.Add($procSpeed)

############################################## end check boxes

############################################## Start drop down boxes

$DropDownBox = New-Object System.Windows.Forms.ComboBox
$DropDownBox.Location = New-Object System.Drawing.Size(20,50) 
$DropDownBox.Size = New-Object System.Drawing.Size(180,20) 
$DropDownBox.DropDownHeight = 200 
$Form.Controls.Add($DropDownBox) 

$wksList=@("hrcomputer1","hrcomputer2","hrcomputer3","workstation1","workstation2","computer5","localhost")

foreach ($wks in $wksList) {
                      $DropDownBox.Items.Add($wks)
                              } #end foreach

############################################## end drop down boxes

############################################## Start text fields

$outputBox = New-Object System.Windows.Forms.RichTextBox 
$outputBox.Location = New-Object System.Drawing.Size(10,150) 
$outputBox.Size = New-Object System.Drawing.Size(565,200) 
$outputBox.MultiLine = $True 

$outputBox.ScrollBars = "Vertical" 
$Form.Controls.Add($outputBox) 

############################################## end text fields

############################################## Start buttons

$Button = New-Object System.Windows.Forms.Button 
$Button.Location = New-Object System.Drawing.Size(400,30) 
$Button.Size = New-Object System.Drawing.Size(110,80) 
$Button.Text = "Get Processor Info" 
$Button.Add_Click({procInformation}) 
$Form.Controls.Add($Button) 

############################################## end buttons

$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

Final result should look like this:

powershell_check_box

powershell_check_box2

Advertisements

Foreach vs Cursor

So what if we have a list and we want to go through it an item at a time?

For fun let’s do this first in PowerShell and then replicate the results using a T-SQL cursor.

Powershell – Foreach

Code:

$GetColor = @("Blue","White","Red","Cyan","Yellow") 

foreach ($ColorProperty in $GetColor) {                            

                                write-host $ColorProperty

                                       } #end foreach

Output:

Blue
White
Red
Cyan
Yellow

T-SQL – Cursor

This being sql, let’s start with a database:

database

table

Code:

declare @ColorProperty char(10)
declare @GetColor cursor

set @GetColor = cursor for select Color FROM test_db1.dbo.table1

open @GetColor
fetch next from @GetColor into @ColorProperty

while @@FETCH_STATUS = 0
Begin

Print @ColorProperty
fetch next from @GetColor into @ColorProperty

End

close @GetColor
deallocate @GetColor

Output:

Blue      
White     
Red       
Cyan      
Yellow

PowerShell GUI for your scripts. Episode 3

Group Boxes | Radio Buttons

Group boxes allow you to … well … group visual elements together.  In particular, they allow multiple sets of radio buttons.

Creating the Group Box

$groupBox = New-Object System.Windows.Forms.GroupBox #create the group box
$groupBox.Location = New-Object System.Drawing.Size(270,20) #location of the group box (px) in relation to the primary window's edges (length, height)
$groupBox.size = New-Object System.Drawing.Size(100,100) #the size in px of the group box (length, height)
$groupBox.text = "Nr of pings:" #labeling the box
$Form.Controls.Add($groupBox) #activate the group box

Creating the radio buttons

$RadioButton1 = New-Object System.Windows.Forms.RadioButton #create the radio button
$RadioButton1.Location = new-object System.Drawing.Point(15,15) #location of the radio button(px) in relation to the group box's edges (length, height)
$RadioButton1.size = New-Object System.Drawing.Size(80,20) #the size in px of the radio button (length, height)
$RadioButton1.Checked = $true #is checked by default
$RadioButton1.Text = "Ping once" #labeling the radio button
$groupBox.Controls.Add($RadioButton1) #activate the inside the group box

Note.  Notice that I added the radio button to the group box and not the form. Two reasons:

  1. Grouping the radio buttons together
  2. By placing radio buttons groups in separate group boxes they can function independently from each other

Note2. Only one radio button per group can be .Checked = $true

Adding to the ping function based on the radio selection

if ($RadioButton1.Checked -eq $true) {$nrOfPings=1} 
if ($RadioButton2.Checked -eq $true) {$nrOfPings=2}
if ($RadioButton3.Checked -eq $true) {$nrOfPings=3}
$pingResult=ping $wks -n $nrOfPings

If you would rather initiate an action upon a radio button selection use the method:

.Add_Click({functionName})

Now for the completed script (adding where we left in Episode 2):

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

$Form = New-Object System.Windows.Forms.Form    
$Form.Size = New-Object System.Drawing.Size(600,400)  

############################################## Start functions

function pingInfo {

if ($RadioButton1.Checked -eq $true) {$nrOfPings=1}
if ($RadioButton2.Checked -eq $true) {$nrOfPings=2}
if ($RadioButton3.Checked -eq $true) {$nrOfPings=3}

$computer=$DropDownBox.SelectedItem.ToString() #populate the var with the value you selected
$pingResult=ping $wks -n $nrOfPings | fl | out-string;
$outputBox.text=$pingResult

                     } #end pingInfo

############################################## end functions

############################################## Start group boxes

$groupBox = New-Object System.Windows.Forms.GroupBox
$groupBox.Location = New-Object System.Drawing.Size(270,20) 
$groupBox.size = New-Object System.Drawing.Size(100,100) 
$groupBox.text = "Nr of pings:" 
$Form.Controls.Add($groupBox) 

############################################## end group boxes

############################################## Start radio buttons

$RadioButton1 = New-Object System.Windows.Forms.RadioButton 
$RadioButton1.Location = new-object System.Drawing.Point(15,15) 
$RadioButton1.size = New-Object System.Drawing.Size(80,20) 
$RadioButton1.Checked = $true 
$RadioButton1.Text = "Ping once" 
$groupBox.Controls.Add($RadioButton1) 

$RadioButton2 = New-Object System.Windows.Forms.RadioButton
$RadioButton2.Location = new-object System.Drawing.Point(15,45)
$RadioButton2.size = New-Object System.Drawing.Size(80,20)
$RadioButton2.Text = "Ping twice"
$groupBox.Controls.Add($RadioButton2)

$RadioButton3 = New-Object System.Windows.Forms.RadioButton
$RadioButton3.Location = new-object System.Drawing.Point(15,75)
$RadioButton3.size = New-Object System.Drawing.Size(80,20)
$RadioButton3.Text = "Ping thrice"
$groupBox.Controls.Add($RadioButton3)

############################################## end radio buttons

############################################## Start drop down boxes

$DropDownBox = New-Object System.Windows.Forms.ComboBox
$DropDownBox.Location = New-Object System.Drawing.Size(20,50) 
$DropDownBox.Size = New-Object System.Drawing.Size(180,20) 
$DropDownBox.DropDownHeight = 200 
$Form.Controls.Add($DropDownBox) 

$wksList=@("hrcomputer1","hrcomputer2","hrcomputer3","workstation1","workstation2","computer5","localhost")

foreach ($wks in $wksList) {
                      $DropDownBox.Items.Add($wks)
                              } #end foreach

############################################## end drop down boxes

############################################## Start text fields

$outputBox = New-Object System.Windows.Forms.TextBox 
$outputBox.Location = New-Object System.Drawing.Size(10,150) 
$outputBox.Size = New-Object System.Drawing.Size(565,200) 
$outputBox.MultiLine = $True 

$outputBox.ScrollBars = "Vertical" 
$Form.Controls.Add($outputBox) 

############################################## end text fields

############################################## Start buttons

$Button = New-Object System.Windows.Forms.Button 
$Button.Location = New-Object System.Drawing.Size(400,30) 
$Button.Size = New-Object System.Drawing.Size(110,80) 
$Button.Text = "Ping" 
$Button.Add_Click({pingInfo}) 
$Form.Controls.Add($Button) 

############################################## end buttons

$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

Final result should look like this (choose the number of pings you want performed)

powershell_GUI_radio_ping

Ping away! 🙂

PowerShell GUI for your scripts. Episode 2

DropDown Lists

Why enter the information manually into a text box when we can have a nice dropdown list with a selection ready?

To start off we need an array:

$wksList=@("hrcomputer1","hrcomputer2","hrcomputer3","workstation1","workstation2","computer5")

You can populate the array using an external file, an active directory query or even an SQL query. In this case we hand built an array for simplicity’s sake

Build the drop down list (we’ll replace the InputBox from the Episode 1 script):

$DropDownBox = New-Object System.Windows.Forms.ComboBox #creating the dropdown list
$DropDownBox.Location = New-Object System.Drawing.Size(20,50) #location of the drop down (px) in relation to the primary window's edges (length, height)
$DropDownBox.Size = New-Object System.Drawing.Size(180,20) #the size in px of the drop down box (length, height)
$DropDownBox.DropDownHeight = 200 #the height of the pop out selection box
$Form.Controls.Add($DropDownBox) #activating the drop box inside the primary window

Populate the drop down list from the array we built earlier:

foreach ($wks in $wksList) {
                      $DropDownBox.Items.Add($wks)
                              } #end foreach

Populate a variable (named $computer in this case) with the value you select in the dropdown:

$computer=$DropDownBox.SelectedItem.ToString()

—————————–

Let’s put it all together. We’ll take the GUI ping script from Episode 1 and replace the InputBox with a dropdown list

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

$Form = New-Object System.Windows.Forms.Form    
$Form.Size = New-Object System.Drawing.Size(600,400)  

############################################## Start functions

function procInfo {
$computer=$DropDownBox.SelectedItem.ToString() #populate the var with the value you selected
$pingResult=ping $computer | fl | out-string;
$outputBox.text=$pingResult
                     } #end procInfo

############################################## end functions

############################################## Start drop down boxes

$DropDownBox = New-Object System.Windows.Forms.ComboBox
$DropDownBox.Location = New-Object System.Drawing.Size(20,50) 
$DropDownBox.Size = New-Object System.Drawing.Size(180,20) 
$DropDownBox.DropDownHeight = 200 
$Form.Controls.Add($DropDownBox) 

$wksList=@("hrcomputer1","hrcomputer2","hrcomputer3","workstation1","workstation2","computer5")

foreach ($wks in $wksList) {
                      $DropDownBox.Items.Add($wks)
                              } #end foreach

############################################## end drop down boxes

############################################## Start text fields

$outputBox = New-Object System.Windows.Forms.TextBox 
$outputBox.Location = New-Object System.Drawing.Size(10,150) 
$outputBox.Size = New-Object System.Drawing.Size(565,200) 
$outputBox.MultiLine = $True 
$outputBox.ScrollBars = "Vertical" 
$Form.Controls.Add($outputBox) 

############################################## end text fields

############################################## Start buttons

$Button = New-Object System.Windows.Forms.Button 
$Button.Location = New-Object System.Drawing.Size(400,30) 
$Button.Size = New-Object System.Drawing.Size(110,80) 
$Button.Text = "Ping" 
$Button.Add_Click({procInfo}) 
$Form.Controls.Add($Button) 

############################################## end buttons

$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

The end result should look like this:

Select a computer name and PING away 🙂

PS might want to add to the array an actual computer name from your network or localhost 😉

PowerShell GUI front end for your scripts. Episode 1

Why? To give your scripts a nice looking interface, to make it user-friendly (can make a script look like an application usable by the other  non IT departments, and last but not least make the script more comfortable to use.

How? Leveraging the power of the .net framework.

—————————————–

Background Window | Single/Multi line Input/Output Box | Action Button

And now let’s get to it:

Part A. Creating the background window:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  #loading the necessary .net libraries (using void to suppress output)

$Form = New-Object System.Windows.Forms.Form    #creating the form (this will be the "primary" window)
$Form.Size = New-Object System.Drawing.Size(600,400)  #the size in px of the window length, height

$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()   #activating the form

Final result should look like this:

—————————————–

Part B. Adding some functional elements:

Creating a single line text box (we’ll use it for input):

$InputBox = New-Object System.Windows.Forms.TextBox #creating the text box
$InputBox.Location = New-Object System.Drawing.Size(20,50) #location of the text box (px) in relation to the primary window's edges (length, height)
$InputBox.Size = New-Object System.Drawing.Size(150,20) #the size in px of the text box (length, height)
$Form.Controls.Add($InputBox) #activating the text box inside the primary window

Creating a multi line text box (we’ll use it for output):

$outputBox = New-Object System.Windows.Forms.TextBox #creating the text box
$outputBox.Location = New-Object System.Drawing.Size(10,150) #location of the text box (px) in relation to the primary window's edges (length, height)
$outputBox.Size = New-Object System.Drawing.Size(565,200) #the size in px of the text box (length, height)
$outputBox.MultiLine = $True #declaring the text box as multi-line
$outputBox.ScrollBars = "Vertical" #adding scroll bars if required
$Form.Controls.Add($outputBox) #activating the text box inside the primary window

Since we have now two fields how about we add an element to generate an action. How about a Button?

$Button = New-Object System.Windows.Forms.Button #create the button
$Button.Location = New-Object System.Drawing.Size(400,30) #location of the button (px) in relation to the primary window's edges (length, height)
$Button.Size = New-Object System.Drawing.Size(110,80) #the size in px of the button (length, height)
$Button.Text = "Action" #labeling the button
$Button.Add_Click({}) #the action triggered by the button
$Form.Controls.Add($Button) #activating the button inside the primary window

All we need now is a script….how about ol’trusty ping :).We’ll make a function of course to keep things nice and proper

function pingInfo {
$wks=$InputBox.text; #we're taking the text from the input box into the variable $wks
$pingResult=ping $wks | fl | out-string;  #ping $wks
$outputBox.text=$pingResult #send the ping results to the output box
                     } #end pingInfo

Next we need to add the function name to the Button’s Add_Click() method

$Button.Add_Click({pingInfo})

—————————————–

Part C. Putting it all together

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

$Form = New-Object System.Windows.Forms.Form    
$Form.Size = New-Object System.Drawing.Size(600,400)  

############################################## Start functions

function pingInfo {
$wks=$InputBox.text;
$pingResult=ping $wks | fl | out-string;
$outputBox.text=$pingResult
                     } #end pingInfo

############################################## end functions

############################################## Start text fields

$InputBox = New-Object System.Windows.Forms.TextBox 
$InputBox.Location = New-Object System.Drawing.Size(20,50) 
$InputBox.Size = New-Object System.Drawing.Size(150,20) 
$Form.Controls.Add($InputBox) 

$outputBox = New-Object System.Windows.Forms.TextBox 
$outputBox.Location = New-Object System.Drawing.Size(10,150) 
$outputBox.Size = New-Object System.Drawing.Size(565,200) 
$outputBox.MultiLine = $True 
$outputBox.ScrollBars = "Vertical" 
$Form.Controls.Add($outputBox) 

############################################## end text fields

############################################## Start buttons

$Button = New-Object System.Windows.Forms.Button 
$Button.Location = New-Object System.Drawing.Size(400,30) 
$Button.Size = New-Object System.Drawing.Size(110,80) 
$Button.Text = "Ping" 
$Button.Add_Click({pingInfo}) 
$Form.Controls.Add($Button) 

############################################## end buttons

$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

Final result should look like this:

Voilà! Your first script with a graphical interface.

But wait we’re not done. Let’s add some optional BLING! 🙂

—————————————–

Part D. Optional decoration elements

Main window

$Form.StartPosition = "CenterScreen" #loads the window in the center of the screen
$Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow #modifies the window border
$Form.Text = "Ping GUI tool" #window description

Modifying the textbox font:

$outputBox.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Italic)

Changing the button cursor onHover to a hand icon, the background color to green and a larger font

$Button.Cursor = [System.Windows.Forms.Cursors]::Hand
$Button.BackColor = [System.Drawing.Color]::LightGreen
$Button.Font = New-Object System.Drawing.Font("Verdana",14,[System.Drawing.FontStyle]::Bold)

Those are just some of the customizations possible, integrate some of them in the GUI objects we created, see what they do…change them at will…have FUN!