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

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()

Related

PowerShell - Using input from TextBox wont work?

I'm trying to make a GUI for an easy tool I need to check if a specific certificate is included in the file and Output the current and next line. This already works.
If I set the variables $INT1 and $Serial1 manually within the code it also works as intended.
e.g. $INT1=31 and $Serial1="5AA61E07726DAC13".
I always get an Error that the variable is empty when inputing the same values into the GUI and clicking OK. What am I doing wrong?
The code:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.StartPosition = "CenterScreen"
$objForm.Size = New-Object System.Drawing.Size(400,250)
$objForm.Topmost = $True
#Label+Textbox first question
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,30)
$objLabel.Size = New-Object System.Drawing.Size(800,20)
$objLabel.Text = "INT of certificate"
$objForm.Controls.Add($objLabel)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)
#Label+Textbox second question
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,130)
$objLabel2.Size = New-Object System.Drawing.Size(800,20)
$objLabel2.Text = "Serialnumber of the certificate"
$objForm.Controls.Add($objLabel2)
$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(10,150)
$objTextBox2.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox2)
$INT1 = $objTextBox.Text;
$Serial1 = $objTextBox2.Text;
#OK Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(100,175)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Name = "OK"
#$OKButton.DialogResult = "OK"
$OKButton.Add_Click({Invoke-WebRequest -Uri http://CENSORED.crl -OutFile crl.crl;
$test=certutil.exe -dump crl.crl |Out-String -stream | Select-String -pattern "$Serial1" -Context 0,1
[void] [Windows.Forms.MessageBox]::Show($test)})
$objForm.Controls.Add($OKButton)
[void] $objForm.ShowDialog()
Thank you!
Here's a rewrite of your code.
I'm assuming that you want variables $INT1 and $Serial1 to be available after the windows closes.
In that case, fill them inside the Click() scriptblock and refer to them using $script: scoping, otherwise they are just new variables local to the scriptblock.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# these variables need to visible inside the Click scriptblock of the button
# and be also available after the windows closes
$INT1 = $null
$Serial1 = $null
$objForm = New-Object System.Windows.Forms.Form
$objForm.StartPosition = "CenterScreen"
$objForm.Size = New-Object System.Drawing.Size(400,250)
$objForm.Topmost = $True
#Label+Textbox first question
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,30)
$objLabel.Size = New-Object System.Drawing.Size(800,20)
$objLabel.Text = "INT of certificate"
$objForm.Controls.Add($objLabel)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)
#Label+Textbox second question
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,130)
$objLabel2.Size = New-Object System.Drawing.Size(800,20)
$objLabel2.Text = "Serialnumber of the certificate"
$objForm.Controls.Add($objLabel2)
$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(10,150)
$objTextBox2.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox2)
#OK Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(100,175)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Name = "OK"
#$OKButton.DialogResult = "OK"
$OKButton.Add_Click({
# you never seem to use variable $INT1, but if you do, refer to it as $script:INT1
# set the variables defined OUTSIDE the scriptblock using script-scoping
$script:INT1 = $objTextBox.Text
$script:Serial1 = $objTextBox2.Text
# create a full path and filename for the output of the Invoke-WebRequest call
$crlFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'crl.crl'
Invoke-WebRequest -Uri 'http://CENSORED.crl' -OutFile $crlFile
$test = certutil.exe -dump $crlFile | Out-String -Stream | Select-String -Pattern $script:Serial1 -Context 0,1
[void] [Windows.Forms.MessageBox]::Show($test)
# delete the temporary file
$crlFile | Remove-Item -Force
})
$objForm.Controls.Add($OKButton)
[void] $objForm.ShowDialog()
# clean up the form from memory'
$objForm.Dispose()
# here you can again see what is inside variables $INT1 and $Serial1
Write-Host "Last entered values: $INT1 $Serial1"
All user interaction with your form happens in this, blocking call:
[void] $objForm.ShowDialog()
See the ShowDialog() method.
Therefore, if you want to store results from that user interaction in variables, place the assignments after the call, and reference the controls of interest.
# ... form setup
# Show the form modally (as a dialog).
# The call blocks until the form is closed.
# Note:
# You may want to examine the return value in case there
# are multiple ways to close your form, and one of those ways
# signals having *canceled*, for instance.
$null = $objForm.ShowDialog()
# Now you can get values from the controls and assign them to (script) variables.
$INT1 = $objTextBox.Text
$Serial1 = $objTextBox2.Text
Note: If you need to set script-level variables - i.e., variables visible after a .ShowDialog() call - from inside script blocks serving as event delegates (e.g., the script block passed to $OKButton.Add_Click()), you need to use the $script: scope, given that such script blocks run in a child scope too - see this answer.

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

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
}

Powershell dialog box with countdown and option to press cancel?

I have been trying to create a Powershell script that performs the following
Shows a dialog box that an update is about to occur
Provide a countdown of say 30 seconds
During the countdown, a user can press "Cancel Update"
If the countdown expires and "Cancel Update" was not pressed, then update will occur
Right before the loop, the window shows if I call $Counter_Form.ShowDialog() and I can click the Cancel button. When clicking, the following should occur.
Window should close after pressing the button. This is correct.
$cancel should be set to $true to indicate that Cancel was pressed. However, it remains $false and this is incorrect. Why is this?
Now, for the problems in the while loop
The window refreshes to show the new delay, but I cannot click "Cancel Update" since it just shows an hourglass icon and seems to be frozen
Script
#Adjust delay here
$delay = 5
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Counter_Form = New-Object System.Windows.Forms.Form
$Counter_Form.Text = "Warning"
#Form size options
$Counter_Form.Width = 350
$Counter_Form.Height = 150
#Centers form on screen
$Counter_Form.StartPosition = "CenterScreen"
#Places form on top of everything else
$Counter_Form.TopMost = $true
$Counter_Label = New-Object System.Windows.Forms.Label
$Counter_Label2 = New-Object System.Windows.Forms.Label
#Label2's text
$Counter_Label2.Text = "Please save all your work"
#Labels size and position
$Counter_Label.AutoSize = $true
$Counter_Label.Location = New-Object System.Drawing.Point(50,60)
$Counter_Label2.AutoSize = $true
$Counter_Label2.Location = New-Object System.Drawing.Point(90,30)
$cancel = $false
$button1 = New-Object System.Windows.Forms.Button
$button1.Text = "Cancel Update";
$button1.Location = New-Object System.Drawing.Point(130,80)
$button1.Add_Click({ $Counter_Form.Close(); $cancel = $true})
$Counter_Form.Controls.Add($Counter_Label)
$Counter_Form.Controls.Add($Counter_Label2)
$Counter_Form.Controls.Add($button1)
#LOOP!
while ($delay -ge 0 -And $cancel -eq $false)
{
$Counter_Form.Show()
#Timer label's text
$Counter_Label.Text = "Update will occur in $($delay) seconds."
start-sleep 1
$delay -= 1
}
$Counter_Form.Close()
For the first question about $cancel not being updated to $true, it is a result of scope.
Add the script scope, with $script:cancel = $true. So that line of code should be:
$button1.Add_Click({ $Counter_Form.Close(); $script:cancel = $true})
I didn't find an exact solution to what I started. A pieced together some code from various sources and found the following worked. I'm posting it here in case it ends up helping someone:
function ShowMsg ($timeout, $message)
{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = "Window Title"
$form.Size = New-Object System.Drawing.Size(300,300)
$form.StartPosition = 'CenterScreen'
$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(280,205)
$form.Controls.Add($label)
#add button to form
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(160,215)
$okButton.Size = New-Object System.Drawing.Size(100,23)
$okButton.Text = 'Cancel Update'
$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(40,215)
$cancelButton.Size = New-Object System.Drawing.Size(100,23)
$cancelButton.Text = 'Allow Update'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::CANCEL
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = $timeout * 1000
$timer.add_tick({$form.Close()})
$timer.Start()
$form.Topmost = $true
$form.ShowDialog()
$form.Dispose()
}
Calling the function:
$timeout = 60 #seconds
$message_response = ShowMsg -timeout $timeout -message "Hello, update is happening"

Powershell Form With Two Text Inputs and drop down selection

I'm very rusty in the area of powershell and trying to pick it back up but I have something bothering me that I can't seem to figure out. I've created a form that has two text inputs for file locations and a drop down list. What I'm attempting to do is compare the two files received in a text input. I've got the script already for the compare but what I'm trying to figure out is how I distinguish the script to be run from the selection of the drop down list and also parse the two text inputs from the form to the relevant compare script. Below is the generic form created. Any help would be much appreciated.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(700,700)
#You can use the below method as well
#$Form.Width = 400
#$Form.Height = 200
$form.MaximizeBox = $false
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = 'Fixed3D'
$Form.Text = "IAM Application Comparison Tool"
#application Drop down list
$Label = New-Object System.Windows.Forms.Label
$Label.Text = "Please select the application being compared"
$Label.AutoSize = $true
$Label.Location = New-Object System.Drawing.Size(10,10)
$Font = New-Object System.Drawing.Font("Arial",15,[System.Drawing.FontStyle]::Bold)
$form.Font = $Font
$Form.Controls.Add($Label)
#list of applications
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,50)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
[void] $listBox.Items.Add('Terradata')
[void] $listBox.Items.Add('')
[void] $listBox.Items.Add('')
[void] $listBox.Items.Add('')
[void] $listBox.Items.Add('')
[void] $listBox.Items.Add('')
[void] $listBox.Items.Add('')
$form.Controls.Add($listBox)
#File path of previous months file
$Label = New-Object System.Windows.Forms.Label
$Label.Text = "Enter file path of previous months file"
$Label.AutoSize = $true
$Label.Location = New-Object System.Drawing.Size(20,200)
$Font = New-Object System.Drawing.Font("Arial",15,[System.Drawing.FontStyle]::Bold)
$form.Font = $Font
$Form.Controls.Add($Label)
#Input file path
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(20,300)
$textBox.Size = New-Object System.Drawing.Size(450,20)
$form.Controls.Add($textBox)
#$formIcon = New-Object system.drawing.icon ("$env:USERPROFILE\desktop\Blog\v.ico")
#$form.Icon = $formicon
#File path of current month
$Label = New-Object System.Windows.Forms.Label
$Label.Text = "Enter file path of current months file"
$Label.AutoSize = $true
$Label.Location = New-Object System.Drawing.Size(20,400)
$Font = New-Object System.Drawing.Font("Arial",15,[System.Drawing.FontStyle]::Bold)
$form.Font = $Font
$Form.Controls.Add($Label)
#Input file path
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(20,500)
$textBox.Size = New-Object System.Drawing.Size(450,20)
$form.Controls.Add($textBox)
#Run Required Compare script
$Okbutton = New-Object System.Windows.Forms.Button
$Okbutton.Location = New-Object System.Drawing.Size(170,600)
$Okbutton.Size = New-Object System.Drawing.Size(200,30)
$Okbutton.Text = "Compare Files"
$Okbutton.Add_Click()
$Form.Controls.Add($Okbutton)
$Form.ShowDialog()
Create a function that will run whenever the button is clicked.
for instance, your button event will be:
$Okbutton.Add_Click({ BtnClick })
then add the function that will do the compare, whenever the button is clicked the function will be called:
function BtnClick{
# do something / compare your texts
#compare $TextBox1.Text $TextBox2.Text
}
you have to give a different variable name for each textbox, this how you'll be able to access the values:
$input1 = $TextBox1.Text
$input2 = $TextBox2.Text
$input3 = $ComboBox1.Text
The easiest way to have your code distinguish between the different objects is to name them upon creation, so use different variable names for the textboxes and the like.
To act on the button click, you already started by writing $Okbutton.Add_Click(), but since there is no scriptblock to actually do something there, nothing would happen.
The listbox can also react on an event, in this case that would be the SelectedIndexChanged event.
Please see the revised code below that shows how to implement these event handlers
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[void] [System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(700,700)
$Form.MaximizeBox = $false
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = 'Fixed3D'
$Form.Text = "IAM Application Comparison Tool"
$Font = New-Object System.Drawing.Font("Arial",15,[System.Drawing.FontStyle]::Bold)
$Form.Font = $Font
#application Drop down list
$LabelDropDown = New-Object System.Windows.Forms.Label
$LabelDropDown.Text = "Please select the application being compared"
$LabelDropDown.AutoSize = $true
$LabelDropDown.Location = New-Object System.Drawing.Size(10,10)
$Form.Controls.Add($LabelDropDown)
# list of applications
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,50)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
# add the items to the listbox
$null = $listBox.Items.AddRange(#('Terradata','SomeApp','MyApp','ThirdPartyApp'))
# set the current selected item to be the first
$listBox.SelectedIndex = 0
# add functionality to react on index changed
$listBox.Add_SelectedIndexChanged({
# do something when the user chose a different app in the listbox
# for demo, just write the currently selected item in the console
Write-Host "Currently selected app in the listbox: $($this.SelectedItem)"
})
$Form.Controls.Add($listBox)
# File path of previous months file
$LabelPrevious = New-Object System.Windows.Forms.Label
$LabelPrevious.Text = "Enter file path of previous months file"
$LabelPrevious.AutoSize = $true
$LabelPrevious.Location = New-Object System.Drawing.Size(20,200)
$Form.Controls.Add($LabelPrevious)
# first Input file path
$textBoxFile1 = New-Object System.Windows.Forms.TextBox
$textBoxFile1.Location = New-Object System.Drawing.Point(20,300)
$textBoxFile1.Size = New-Object System.Drawing.Size(450,20)
$Form.Controls.Add($textBoxFile1)
# File path of current month
$LabelCurrent = New-Object System.Windows.Forms.Label
$LabelCurrent.Text = "Enter file path of current months file"
$LabelCurrent.AutoSize = $true
$LabelCurrent.Location = New-Object System.Drawing.Size(20,400)
$Form.Controls.Add($LabelCurrent)
# second Input file path
$textBoxFile2 = New-Object System.Windows.Forms.TextBox
$textBoxFile2.Location = New-Object System.Drawing.Point(20,500)
$textBoxFile2.Size = New-Object System.Drawing.Size(450,20)
$Form.Controls.Add($textBoxFile2)
# Run Required Compare script
$Okbutton = New-Object System.Windows.Forms.Button
$Okbutton.Location = New-Object System.Drawing.Size(170,600)
$Okbutton.Size = New-Object System.Drawing.Size(200,30)
$Okbutton.Text = "Compare Files"
# add functionality for comparing files
$Okbutton.Add_Click({
# your compare function comparing the file in $textbox1 against the file in $textbox2
# IF both fields contain a valid file path and name of course ;)
# for demo just output in console
Write-Host "Compare file '$($textBoxFile1.Text)' to '$($textBoxFile2.Text)'"
})
$Form.Controls.Add($Okbutton)
$Form.ShowDialog()
# important! dispose of the form when done
$Form.Dispose()
P.S. Inside the scriptblocks for the Click and the SelectedIndexChanged events, you can use automatic variable $this, which refers to the current form control object.

Powershell mask password

I would like to prompt user to enter a list of passwords, one line at a time. When the person types the passwords, it should appear as *
I have a function
function Read-MultiLineInputBoxDialogPwd([string]$Message, [string]$WindowTitle, [string]$DefaultText){
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
# Create the label
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Size(10,10)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.AutoSize = $true
$label.Text = $Message
# Create the TextBox used to capture the user's text
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Size(10,40)
$textBox.Size = New-Object System.Drawing.Size(575,200)
$textBox.AcceptsReturn = $true
$textBox.AcceptsTab = $false
$textBox.Multiline = $true
$textBox.ScrollBars = 'Both'
$textBox.Text = $DefaultText
$textBox.UseSystemPasswordChar = $True
# Create the OK button.
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Size(415,250)
$okButton.Size = New-Object System.Drawing.Size(75,25)
$okButton.Text = "OK"
$okButton.Add_Click({ $form.Tag = $textBox.Text; $form.Close() })
# Create the Cancel button.
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Size(510,250)
$cancelButton.Size = New-Object System.Drawing.Size(75,25)
$cancelButton.Text = "Cancel"
$cancelButton.Add_Click({ $form.Tag = $null; $form.Close() })
# Create the form.
$form = New-Object System.Windows.Forms.Form
$form.Text = $WindowTitle
$form.Size = New-Object System.Drawing.Size(610,320)
$form.FormBorderStyle = 'FixedSingle'
$form.StartPosition = "CenterScreen"
$form.AutoSizeMode = 'GrowAndShrink'
$form.Topmost = $True
$form.AcceptButton = $okButton
$form.CancelButton = $cancelButton
$form.ShowInTaskbar = $true
# Add all of the controls to the form.
$form.Controls.Add($label)
$form.Controls.Add($textBox)
$form.Controls.Add($okButton)
$form.Controls.Add($cancelButton)
# Initialize and show the form.
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() > $null # Trash the text of the button that was clicked.
# Return the text that the user entered.
return $form.Tag
}
And I call the function
$multiLineTextPwd = Read-MultiLineInputBoxDialogPwd -Message "All possible passwords" -WindowTitle "Passwords" -DefaultText "Please enter all possible passwords, one line at a time..."
But when it pops up, the text still appears in plaintext, even though I set the following
$textBox.UseSystemPasswordChar = $True
How to fix this?
I honestly feel that this would be better accomplished by having a single-line text box and an 'Add Another Password' button where the user could enter a password, and then click the button to add another password. You would just keep adding them to an array, and would have to make sure that when they submit that it checks for anything in that box and adds anything left to the array before performing actions.
All password masking references when I went and looked at the MSDN listing for the Textbox class all specifically state Single Line Textbox, so it may well be that you can't use masking with a multiline textbox.
If you read the documentation here you'll see that for multiline text boxes, the UseSystemPasswordChar has no effect.
implement keydown event of mutiline textbox, append * into TB, and append key code string into a string variable.