How to return a SelectedItems value when listbox items are inside an "add_SelectedValueChanged" block - powershell

After selecting an option from the drop down list ($RCVROption), when choosing an option from the list provided ($listBox), the $listBox.SelectedItems values are always Null. How do I get those values to assign to variable $x
This is the script I tried, my goal is to have the text from $listBox.SelectedItems to be used as a value that represents a file name, so that when you select an option from the list, and click OK, it runs that file.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
$form = New-Object System.Windows.Forms.Form
$form.Text = 'DMP Receiver Tail'
$form.Size = New-Object System.Drawing.Size(400,300)
$form.StartPosition = 'CenterScreen'
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(115,220)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(190,220)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(60,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Which Receiver Would You Like To Tail?:'
$form.Controls.Add($label)
$RCVROption = new-object System.Windows.Forms.combobox
$RCVROption.Location = new-object System.Drawing.Size(20,40)
$RCVROption.Size = new-object System.Drawing.Size(335,30)
[void] $RCVROption.Items.Add('Receiver 560')
[void] $RCVROption.Items.Add('Receiver 2560')
$RCVROption.tabIndex = '0'
$RCVROption.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList;
$RCVROption.add_SelectedValueChanged(
{
if($RCVROption.SelectedItem -eq 'Receiver 560')
{
$listBox = New-Object System.Windows.Forms.Listbox
$listBox.Location = New-Object System.Drawing.Point(40,100)
$listBox.Size = New-Object System.Drawing.Size(260,80)
$listBox.SelectionMode = 'MultiExtended'
[void] $listBox.Items.Add('DMP-560-Line1')
[void] $listBox.Items.Add('DMP-560-Line2')
[void] $listBox.Items.Add('DMP-560-Line3')
[void] $listBox.Items.Add('DMP-560-Line4')
[void] $listBox.Items.Add('DMP-560-Line5')
$form.Controls.Add($listBox)
}
ELSEIF($RCVROption.SelectedItem -eq 'Receiver 2560')
{
$listBox = New-Object System.Windows.Forms.Listbox
$listBox.Location = New-Object System.Drawing.Point(40,100)
$listBox.Size = New-Object System.Drawing.Size(260,80)
$listBox.SelectionMode = 'MultiExtended'
[void] $listBox.Items.Add('DMP-2560-Line1')
[void] $listBox.Items.Add('DMP-2560-Line2')
[void] $listBox.Items.Add('DMP-2560-Line3')
[void] $listBox.Items.Add('DMP-2560-Line4')
[void] $listBox.Items.Add('DMP-2560-Line5')
$form.Controls.Add($listBox)
}
}
)
$form.Controls.Add($RCVROption)
$form.Topmost = $true
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $listBox.SelectedItems
$Fpath = 'D:\Toolbar\On Call\DMP-Tail\' + $x + '.exe'
Start-process -filepath $FPath
$Fpath
}

Based on your code, I'm guessing you come from a C# background. PowerShell does something weird where it can normally reach outside of script block's scope {code in scriptblock} and use variables that already exist at the time the scriptblock is executed. But it can't easily create or add new variables in the parent/outer scope.
Your code is creating $listBox inside the $RCVROption.add_SelectedValueChanged({code in scriptblock}) event scriptblock, and adding it to the controls for the form, so it continues to exist in the form, but not at the global/script scope of the your code.
I've reworked your code in a format that I've been learning over the last year. Everything you had should still be there, only in a more condensed form. You don't have to use this format, but I personally really like it. How PowerShell converts things like "Cancel" into [System.Windows.Forms.DialogResult]::Cancel is a bit of a mistery to me, but this type of conversion seems very reliable.
This version of the code creates the $listBox prior to firing of the $RCVROption.add_SelectedValueChanged event, clears the items in $listBox, and then populates the ListBox with the new values. The values are in an array, and piped into the [void] $listBox.Items.Add($_) command, executing it once per item in the array.
using namespace System.Windows.Forms
using namespace System.Drawing
Set-StrictMode -Version 3.0
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[Application]::EnableVisualStyles()
$form = [Form]#{
Text = 'DMP Receiver Tail'
Size = "400,300"
StartPosition = 'CenterScreen'
Topmost = $true
}
$OKButton = [Button]#{
DialogResult = "OK"
Location = "115,220"
Size = "75,23"
Text = 'OK'
}
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)
$CancelButton = [Button]#{
DialogResult = "Cancel"
Location = "190,220"
Size = "75,23"
Text = 'Cancel'
}
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)
$label = [Label]#{
Location = "60,20"
Size = "280,20"
Text = 'Which Receiver Would You Like To Tail?:'
}
$form.Controls.Add($label)
$RCVROption = [ComboBox]#{
DropDownStyle = "DropDownList"
Location = "20,40"
Size = "335,30"
tabIndex = '0'
}
[void] $RCVROption.Items.Add('Receiver 560')
[void] $RCVROption.Items.Add('Receiver 2560')
$listBox = [Listbox]#{
Location = "40,100"
SelectionMode = 'MultiExtended'
Size = "260,80"
}
$form.Controls.Add($listBox)
$RCVROption.add_SelectedValueChanged({
if($RCVROption.SelectedItem -eq 'Receiver 560') {
$listBox.Items.Clear()
'DMP-560-Line1', 'DMP-560-Line2', 'DMP-560-Line3', 'DMP-560-Line4', 'DMP-560-Line5' | ForEach-Object {
[void] $listBox.Items.Add($_)
}
}
elseif($RCVROption.SelectedItem -eq 'Receiver 2560') {
$listBox.Items.Clear()
'DMP-2560-Line1', 'DMP-2560-Line2', 'DMP-2560-Line3', 'DMP-2560-Line4', 'DMP-2560-Line5' | ForEach-Object {
[void] $listBox.Items.Add($_)
}
}
})
$form.Controls.Add($RCVROption)
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
$x = $listBox.SelectedItems
$Fpath = 'D:\Toolbar\On Call\DMP-Tail\' + $x + '.exe'
Start-process -filepath $FPath
$Fpath
}

Related

Im having promlen with button functions in gui powershell

I am struggling here. i cannot figure out how to make the button functions read the $listbox1.selectedItems and $listbox2.selectedItem
whats wrong here?
if i try to look at the $listbox items after the OK button been pressed it will show me but not if i call the function button, ive deleted some unneccesery code parts.
$form = New-Object System.Windows.Forms.Form
$form.StartPosition = 'CenterScreen'
$button1 = New-Object System.Windows.Forms.Button
$button1.Text = 'Link'
$button2 = New-Object System.Windows.Forms.Button
$button2.Text = 'UnLink'
$button3 = New-Object System.Windows.Forms.Button
$button3.Text = 'ShowGPOlink'
$button4 = New-Object System.Windows.Forms.Button
$button4.Text = 'ShowOUlink'
#OK Button
$button5 = New-Object System.Windows.Forms.Button
$button5.Text = 'Done'
$button5.DialogResult = [System.Windows.Forms.DialogResult]::OK
$listBox1 = New-Object System.Windows.Forms.ListBox
$listbox1.SelectionMode = 'MultiExtended'
$listBox2 = New-Object System.Windows.Forms.ListBox
[void] $listBox1.Items.addRange($GPOLIST)
[void] $listBox2.Items.Addrange($OUHOLDER.CanonicalName)
$form.Controls.Add(...)
$form.AcceptButton = $button5
$button1.Add_Click({ LinkFn })
$button2.Add_Click({ UnLinkFn })
$button3.Add_Click({ ShowGPO })
$button4.Add_Click({ ShowOU })
function LinkFn {
#for some reason it returns nothing
$listBox1.selecteditems
$listbox2.SelectedItem
Write-Host "function link"
}
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK){
$listBox1.selecteditems
$listbox2.SelectedItem }
Why are you not leveraging the provided PowerShell docs examples and tweaking as needed:
Selecting Items from a List Box
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please select a computer:'
$form.Controls.Add($label)
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,40)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
[void] $listBox.Items.Add('atl-dc-001')
[void] $listBox.Items.Add('atl-dc-002')
[void] $listBox.Items.Add('atl-dc-003')
[void] $listBox.Items.Add('atl-dc-004')
[void] $listBox.Items.Add('atl-dc-005')
[void] $listBox.Items.Add('atl-dc-006')
[void] $listBox.Items.Add('atl-dc-007')
$form.Controls.Add($listBox)
$form.Topmost = $true
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $listBox.SelectedItem
$x
}
If you have the Multiselect defined, then change the block to this...
$listBox.SelectionMode = 'MultiExtended'
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
ForEach ($ListItem in $listBox.SelectedItems)
{$ListItem}
}
So, as I said, this required me to physically re-write what you have here to explain and show you what you would be looking at. This will show the formatted GUI, with a prepopulated list, that when you single or multi-select and item from listbox1, and click the Link button, which fires the function LinkFn, it will copy that selection to Listbox2 and will not close the form.
The below code is not doing anything differently than what is shown in the PS help other than sending the results to another GUI element, and not closing the form via the default OK return. All of which is a common thing in GUI design.
#region Begin environment initialization
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
#endregion Begin environment initialization
#region Begin functions and code behind
function DoneFn { }
function ShowModuleFn { }
function ShowProcessFn { }
function UnLinkFn { }
function LinkFn
{
$listBox1.selecteditems
# $listbox2.SelectedItems
[void] $listBox2.Items.Addrange($listBox1.selecteditems)
}
$List1 = (Get-Process).Name
# $List2 = (Get-Module).Name
#endregion End functions and code behind
#region Begin GUI code
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '634,339'
$Form.text = 'Form'
$Form.TopMost = $false
$ListBox1 = New-Object system.Windows.Forms.ListBox
$ListBox1.text = 'listBox1'
$listBox1.SelectionMode = 'MultiExtended'
$ListBox1.width = 269
$ListBox1.height = 176
$ListBox1.location = New-Object System.Drawing.Point(17,21)
$ListBox2 = New-Object system.Windows.Forms.ListBox
$ListBox2.text = 'listBox2'
$listBox2.SelectionMode = 'MultiExtended'
$ListBox2.width = 300
$ListBox2.height = 175
$ListBox2.location = New-Object System.Drawing.Point(318,21)
$Button1 = New-Object system.Windows.Forms.Button
$Button1.text = 'Link'
$Button1.width = 60
$Button1.height = 30
$Button1.location = New-Object System.Drawing.Point(20,238)
$Button1.Font = 'Microsoft Sans Serif,10'
$Button2 = New-Object system.Windows.Forms.Button
$Button2.text = 'Unlink'
$Button2.width = 60
$Button2.height = 30
$Button2.location = New-Object System.Drawing.Point(127,241)
$Button2.Font = 'Microsoft Sans Serif,10'
$Button3 = New-Object system.Windows.Forms.Button
$Button3.text = 'ShowProcess'
$Button3.width = 88
$Button3.height = 30
$Button3.location = New-Object System.Drawing.Point(20,297)
$Button3.Font = 'Microsoft Sans Serif,10'
$Button4 = New-Object system.Windows.Forms.Button
$Button4.text = 'ShowModules'
$Button4.width = 105
$Button4.height = 30
$Button4.location = New-Object System.Drawing.Point(127,297)
$Button4.Font = 'Microsoft Sans Serif,10'
$Button5 = New-Object system.Windows.Forms.Button
$Button5.text = 'Done'
$Button5.width = 60
$Button5.height = 30
$Button5.location = New-Object System.Drawing.Point(556,298)
$Button5.Font = 'Microsoft Sans Serif,10'
$Form.controls.AddRange(#(
$ListBox1,
$ListBox2,
$Button1,
$Button2,
$Button3,
$Button4,
$Button5
))
$Button1.Add_Click({ LinkFn })
$Button2.Add_Click({ UnLinkFn })
$Button3.Add_Click({ ShowProcessFn })
$Button4.Add_Click({ ShowModuleFn })
$Button5.Add_Click({ DondFn })
[void] $listBox1.Items.addRange($List1)
# [void] $listBox2.Items.Addrange($List2)
#endregion End GUI code
# Call the GUI
[void]$Form.ShowDialog()

Returning multiple values from multiple drop-downs in Powershell

I am a very new to powershell. I was tasked with creating a GUI that takes in several strings from multiple drop-downs and renames the computer according to those choices. I am testing it with two options, $FacilityInitials and $BuildingNumber. Powershell is returning only the $BuildingNumber choice.
I may be doing something wrong with returning? How should I do multiple return fuctions properly? Thank you! :)
I tried checking for typos.
#Edit This item to change the DropDown Values
[array]$DropDownArray1 = "LI", "BE", "HA"
# This Function Returns the Selected Value and Closes the Form
function Return-DropDown {
$script:Choice = $DropDown1.SelectedItem.ToString()
$Form.Close()
}
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.width = 350
$Form.height = 200
$Form.Text = ”Computer Renamer”
$DropDown1 = new-object System.Windows.Forms.ComboBox
$DropDown1.Location = new-object System.Drawing.Size(100,30)
$DropDown1.Size = new-object System.Drawing.Size(130,30)
ForEach ($Item in $DropDownArray1) {
[void] $DropDown1.Items.Add($Item)
}
$Form.Controls.Add($DropDown1)
$DropDown1Label = new-object System.Windows.Forms.Label
$DropDown1Label.Location = new-object System.Drawing.Size(10,30)
$DropDown1Label.size = new-object System.Drawing.Size(100,20)
$DropDown1Label.Text = "Facility Initials:"
$Form.Controls.Add($DropDown1Label)
################################################################################
#Edit This item to change the DropDown Values
[array]$DropDownArray2 = "01", "02", "03"
# This Function Returns the Selected Value and Closes the Form
function Return-DropDown {
$script:Choice2 = $DropDown2.SelectedItem.ToString()
$Form.Close()
}
$DropDown2 = new-object System.Windows.Forms.ComboBox
$DropDown2.Location = new-object System.Drawing.Size(100,60)
$DropDown2.Size = new-object System.Drawing.Size(130,30)
ForEach ($Item in $DropDownArray2) {
[void] $DropDown2.Items.Add($Item)
}
$Form.Controls.Add($DropDown2)
$DropDown2Label = new-object System.Windows.Forms.Label
$DropDown2Label.Location = new-object System.Drawing.Size(10,60)
$DropDown2Label.size = new-object System.Drawing.Size(100,20)
$DropDown2Label.Text = "Building Number:"
$Form.Controls.Add($DropDown2Label)
################################################################################
#Button
$Button = new-object System.Windows.Forms.Button
$Button.Location = new-object System.Drawing.Size(100,130)
$Button.Size = new-object System.Drawing.Size(150,20)
$Button.Text = "Rename Computer"
$Button.Add_Click({Return-DropDown})
$form.Controls.Add($Button)
################################################################################
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
$FacilityInitials = $Choice
$BuildingNumber = $Choice2
$newCompName = $FacilityInitials + "-" + $BuildingNumber
$AdminAcc = ""
#Add Restart and Force later
Rename-Computer -NewName $newCompName -DomainCredential $AdminAcc

How do I properly use a function in a do/while loop?

I have created a function that creates a specific UI element with text input forms. This form also has three buttons:
One is supposed to display the text inputs again to do the same function again.
Another is supposed to finish and close the UI, passing the text input into the variables.
The last is supposed to cancel the UI element, doing nothing with anything in the text input forms.
Now I know the loop in the code isn't really complete, but I am having issues with it even performing the loop as well as passing the text forms into the variables. I know its something I am doing but it seems correct to me when I look at it.
Changed from an if loop, a while loop, and now a do/while loop.
Changed the position of the variables between the do section into the while section. Same for the if and while loops.
do {
ChangeDesc
}
while ($result -eq [System.Windows.Forms.DialogResult]::Retry)
{
$PC = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $HNInputBox.Text
$PC.Description = $DescInputBox.Text
$PC.Put()
}
ChangeDesc is the name of the function and works just as intended.
Expected to work is to loop the function 'ChangeDesc', and then when the 'Retry' or 'Ok' button is pressed, pass those forms to the variables as shown.
Currently, it will display the form, and when the 'Retry' button is pressed, the forms are passed properly and then the UI is closed out, the 'Ok' button does not pass any input and the 'Cancel' does the same thing.
Below is the rest of my lines of code for clarification.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function ChangeDesc {
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(300,210)
$form.StartPosition = 'CenterScreen'
$AnotherButton = New-Object System.Windows.Forms.Button
$AnotherButton.Location = New-Object System.Drawing.Point(15,130)
$AnotherButton.Size = New-Object System.Drawing.Size(75,23)
$AnotherButton.Text = 'Another?'
$AnotherButton.DialogResult = [System.Windows.Forms.DialogResult]::Retry
$form.AcceptButton = $AnotherButton
$form.Controls.Add($AnotherButton)
$FinishedButton = New-Object System.Windows.Forms.Button
$FinishedButton.Location = New-Object System.Drawing.Point(100,130)
$FinishedButton.Size = New-Object System.Drawing.Size(75,23)
$FinishedButton.Text = 'Finished'
$FinishedButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.CancelButton = $FinishedButton
$form.Controls.Add($FinishedButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(185,130)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)
$HNLabel = New-Object System.Windows.Forms.Label
$HNLabel.Location = New-Object System.Drawing.Point(10,20)
$HNLabel.Size = New-Object System.Drawing.Size(280,20)
$HNLabel.Text = 'Enter Host Name:'
$form.Controls.Add($HNLabel)
$HNInputBox = New-Object System.Windows.Forms.TextBox
$HNInputBox.Location = New-Object System.Drawing.Point(10,40)
$HNInputBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($HNInputBox)
$DescLabel = New-Object System.Windows.Forms.Label
$DescLabel.Location = New-Object System.Drawing.Point(10,70)
$DescLabel.Size = New-Object System.Drawing.Size(280,20)
$DescLabel.Text = 'Enter Description:'
$form.Controls.Add($DescLabel)
$DescInputBox = New-Object System.Windows.Forms.TextBox
$DescInputBox.Location = New-Object System.Drawing.Point(10,90)
$DescInputBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($DescInputBox)
$form.Topmost = $true
$form.Add_Shown({$HNInputBox.Select()})
$result = $form.ShowDialog()
}
Your form is already closed when the loop terminates, and the variables you're trying to use are local to your function. Assign the values you're trying to use to script- or global-scope variables at the end of the function, and the code should do what you expect:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function ChangeDesc {
$form = New-Object Windows.Forms.Form
...
$script:result = $form.ShowDialog()
$script:hostname = $HNInputBox.Text
$script:description = $DescInputBox.Text
}
do {
ChangeDesc
} while ($script:result -eq [Windows.Forms.DialogResult]::Retry)
$PC = Get-WmiObject Win32_OperatingSystem -Computer $script:hostname
$PC.Description = $script:description
$PC.Put()

Storing variable from listbox

I'm attempting to gather user input and store it using $contacttype later on in my script. Originally I was using a simple text input, however I'm now trying to use a listbox to get user input instead.
Originally I was doing this:
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$contacttype = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the contact type", " ")
However, I'm now trying to use a listbox with something like:
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,40)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
[void] $listBox.Items.Add("VPN")
[void] $listBox.Items.Add("Phone")
[void] $listBox.Items.Add("E-mail")
$form.Controls.Add($listBox)
$form.Topmost = $True
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $listBox.SelectedItem
$x
}
How do I make sure $contacttype is populated with the output from the selected listbox item?
Per your answer, you just need to make sure you return your result to the $contacttype variable. However the code you provided wasn't complete, it didn't include the part that initiated $form or add an OK button to trigger the ok result.
Here's a complete version that I've also moved in to a function to show how you could make this a little more reusable:
Function Invoke-ListForm {
Param(
[string[]] $ListItem
)
$Form = New-Object system.Windows.Forms.Form
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,40)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
ForEach ($Item in $ListItem) {
[void] $listBox.Items.Add($Item)
}
$listBox.Add_Click({ $listBox.SelectedItem })
$Form.Controls.Add($listBox)
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$Form.AcceptButton = $OKButton
$Form.Controls.Add($OKButton)
$Form.Topmost = $True
$Result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$listBox.SelectedItem
}
}
$ContactType = Invoke-ListForm VPN,Phone,E-mail
$ContactType

Powershell Cancel button Doesn't Call Function

I have script that creates pop-up with checkbox.
If checkbox is checked and OK is pressed, $districtArray[1] is True
BUT
If checkbox is checked and CANCEL is pressed, $districtArray[1] is ALSO True
I wish that CANCEL button will make entire $districtArray FALSE.
Hence I included function initArray when CANCEL is clicked
$CancelButton.Add_Click({initArray; $Form.Close()})
And here is entire script for reference
$i = $NULL
$districtArray = #()
$highestDistrict = 33
function initArray{
for ($i = 0; $i -lt $highestDistrict; $i++)
{
$script:districtArray += #($false)
}
}
function checkbox_test{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# Set the size of your form
$Form = New-Object System.Windows.Forms.Form
$Form.width = 500
$Form.height = 200
$Form.Text = ”Select District”
# Set the font of the text to be used within the form
$Font = New-Object System.Drawing.Font("Times New Roman",12)
$Form.Font = $Font
# create your checkbox
$checkbox1 = new-object System.Windows.Forms.checkbox
$checkbox1.Location = new-object System.Drawing.Size(30,30)
$checkbox1.Size = new-object System.Drawing.Size(250,50)
$checkbox1.Text = "01"
$checkbox1.Checked = $false
$Form.Controls.Add($checkbox1)
# Add an OK button
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = new-object System.Drawing.Size(130,100)
$OKButton.Size = new-object System.Drawing.Size(100,40)
$OKButton.Text = "OK"
$OKButton.Add_Click({$Form.Close()})
$form.Controls.Add($OKButton)
#Add a cancel button
$CancelButton = new-object System.Windows.Forms.Button
$CancelButton.Location = new-object System.Drawing.Size(255,100)
$CancelButton.Size = new-object System.Drawing.Size(100,40)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({initArray; $Form.Close()})
$form.Controls.Add($CancelButton)
########### This is the important piece ##############
# #
# Do something when the state of the checkbox changes #
#######################################################
$checkbox1.Add_CheckStateChanged({
if ($checkbox1.Checked){$districtArray[1] = $true} })
# Activate the form
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
initArray
#Call the function
checkbox_test
write-host "Value of districtArray[1] is" $districtArray[1]