How to have multiple input fields in the same input box - powershell

I would like to have a tech enter in the username and the group name but in one input box. Anyone willing to tell me how to do this?
Function add-togroup{
#Adds members to group in AD
#$users = Read-Host "Enter a username"
Add-Type -AssemblyName Microsoft.VisualBasic;
$value = [Microsoft.VisualBasic.Interaction]::InputBox('Enter username',
'Username')
$value2 = [Microsoft.VisualBasic.Interaction]::InputBox('Enter group
name', 'XA Group','')
$group_membership = Get-ADPrincipalGroupMembership $users | select name |
format-table -auto
foreach($u in $value)
{
Add-ADGroupMember $value2 -Members $u
}
Write-Host $group_membership
}
So I am capable of using multiple dialogs in sequence but it would make for a better user experience if I could roll this into one single box /form.

If you are not satisfied with the basic forms available then one option you have is to roll your own in PowerShell with .Net forms. Just to show an example that you can build from...
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Data Entry Form"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({
if ($_.KeyCode -eq "Enter" -or $_.KeyCode -eq "Escape"){
$objForm.Close()
}
})
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please enter the information in the space below:"
$objForm.Controls.Add($objLabel)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,40)
$objTextBox.Size = New-Object System.Drawing.Size(260,20)
$objForm.Controls.Add($objTextBox)
$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(10,70)
$objTextBox2.Size = New-Object System.Drawing.Size(260,20)
$objForm.Controls.Add($objTextBox2)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void]$objForm.ShowDialog()
$objTextBox.Text
$objTextBox2.Text
The borrows heavily from the great primer on the subject on TechNet which you should read as it walks you though this better. I removed some of the variable population logic as it was flawed and added another text box. The last two lines return the values entered by the "user". Aside from the addition of the text box I have left most other cosmetic changes up to you to help you get a better understanding of what is involved here.
Keep in mind the locations and sizes of newly added objects and be sure you actually add it to the form.
Since there is not GUI for form building it can seem daunting but its not really that hard to do. You just need to experiment. If you are so inclined there are 3rd party tools that will help with that.

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.

Password Reset with GUI Improvements

I am working on a Password Reset Script with a GUI and have 3 questions If any body is able to help me :) the premise is that when I user scans their card it will show their username and password, it functions as it should be I want to develop it further.
If the box is empty and ‘okay’ is selected then it uses every row in the CSV, is there a way to set it up so the OK button can't be pressed until something is entered. The RFID scanner used always hits a return.
After the pop box has been displayed I want to add a timer for 15 seconds before it closed and then when the pop-up box disappears it then asks for the next person to scan their card. As it stands at the moment, when the message box appears it closes the original form. Is there any way for me to keep the entry form open rather than it shutting, and show the message box over the top of the form? I basically want to reset the form after the user has been given their details.
When I have the form created at the top I can style it. Am I able to do the same for the message box so it can be styled? Thank you so much in advance.
Any help would be massively appreciated. I am still learning the basics of PowerShell
Code
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$Spreadsheet = Import-CSV "C:\Desktop\Password Reset\Passwords.csv" -Header First,Second,Username,Password,RFID
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Password Reset System'
$form.Size = New-Object System.Drawing.Size(800,600) #Box Size
$form.StartPosition = 'CenterScreen'
$Form.BackColor = "#A4F9F4"
$Form.ForeColor = "#000000"
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(350,350) #OK Button Location
$okButton.Size = New-Object System.Drawing.Size(100,24) #OK Button Size
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(270,300) #Label Location
$label.Size = New-Object System.Drawing.Size(280,20) #Label Size
$label.Text = 'Scan your Card:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(270,320) #Textbox Location
$textBox.Size = New-Object System.Drawing.Size(260,20) #Textbox Size
$form.Controls.Add($textBox)
$form.Topmost = $true
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$resetCardNumber = $textBox.Text
$targetUser = $Spreadsheet | Where-Object RFID -eq $resetCardNumber
}
if($targetUser){
Set-ADAccountPassword $targetUser.Username -Reset -NewPassword (Convertto-Securestring -AsPlainText $targetUser.Password -Force)
#Write-Host "Password reset to $($targetUser.Password) for $($targetUser.First) $($targetUser.Second) "($($targetUser.Username))" with card number $($targetUser.RFID)"
[System.Windows.MessageBox]::Show("Your Username: $($targetUser.Username) `nYour Password: $($targetUser.Password) ")
}
else {
#Write-Host "User with Card Number '$resetCardNumber' could not be found!"
[System.Windows.MessageBox]::Show("Your Username could not be found in the system")
}
CSV File below:
First,Second,Username,Password,RFID
John,Smith,JS219401,YourPassword,84192011
Barry,Henry,BH219401,YourPassword,92832839
Hopefully, below (read the inline comments) explains your questions 1 and 2.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
$Spreadsheet = Import-CSV "C:\Desktop\Password Reset\Passwords.csv" -Header First,Second,Username,Password,RFID
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Password Reset System'
$form.Size = New-Object System.Drawing.Size(800,600) #Box Size
$form.StartPosition = 'CenterScreen'
$Form.BackColor = "#A4F9F4"
$Form.ForeColor = "#000000"
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(350,350) #OK Button Location
$okButton.Size = New-Object System.Drawing.Size(100,24) #OK Button Size
$okButton.Text = 'OK'
# remove the next line if you want the mainform to stay open
# $okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
# initialize the button's Enabled status to $false
$okButton.Enabled = $false
# add event handler code for the button's Click event
# this can only be the case if the button was Enabled
$okButton.Add_Click({
$resetCardNumber = $textBox.Text
$targetUser = $Spreadsheet | Where-Object {$_.RFID -eq $resetCardNumber}
if($targetUser){
Set-ADAccountPassword $targetUser.Username -Reset -NewPassword (Convertto-Securestring -AsPlainText $targetUser.Password -Force)
#Write-Host "Password reset to $($targetUser.Password) for $($targetUser.First) $($targetUser.Second) "($($targetUser.Username))" with card number $($targetUser.RFID)"
[System.Windows.MessageBox]::Show("Your Username: $($targetUser.Username) `nYour Password: $($targetUser.Password) ")
}
else {
#Write-Host "User with Card Number '$resetCardNumber' could not be found!"
[System.Windows.MessageBox]::Show("Your Username could not be found in the system")
}
# reset the form by clearing out the textbox
$textBox.Text = '' # this also triggers the OK button to become disabled
})
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(270,300) #Label Location
$label.Size = New-Object System.Drawing.Size(280,20) #Label Size
$label.Text = 'Scan your Card:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(270,320) #Textbox Location
$textBox.Size = New-Object System.Drawing.Size(260,20) #Textbox Size
# add a TextChanged event handler to toggle the OK button's Enabled status
$textBox.Add_TextChanged({
$okButton.Enabled = (![string]::IsNullOrWhiteSpace($this.Text))
})
$form.Controls.Add($textBox)
$form.Topmost = $true
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
# Important, remove the form from memory when done
$form.Dispose()
I'm not really sure what you mean with the third question though: "Am I able to do the same for the message box so it can be styled?"
Since you're using a System.Windows.MessageBox, there is nothing you can do about its default appearance, since A message box is a prefabricated modal dialog box that displays a text message to a user.
If you want a self-styled messagebox, you'll have to create one yourself.

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.

How to program a command button to use a string in powershell

I am writing a Powershell script to automate the install of printers on our network. I have overthinking in place however, I cant seem to get my command button to allow the user to select the printer from a list and set it as default.
I have a string setup to define the printers (4 of them) but no matter what way I code the $OKButton.Add_Click it wont go with the users selection.
Here is the code I have. Can someone please tell me what I am missung?
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a Printer"
$objForm.Size = New-Object System.Drawing.Size(400,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$x=$objListBox.SelectedItem;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$objForm.Close()}})
#Ok Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$objListBox.SelectedItem;$strPrinter,$objForm.Close()})
$objForm.Controls.Add($OKButton)
#Cancel Button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please select a printer:"
$objForm.Controls.Add($objLabel)
#List box showing printer options
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(360,20)
$objListBox.Height = 80
[void] $objListBox.Items.Add("HP Color LaserJet CP2020")
[void] $objListBox.Items.Add("Brother DCP-8065DN")
[void] $objListBox.Items.Add("Canon iR-ADV C2220/2230")
[void] $objListBox.Items.Add("HP LJ300-400 color M351-M451")
$objForm.Controls.Add($objListBox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
#String to call printers, each printer is assigned a value (1,2,3,4)
$strPrinter = 1, "HP Color LaserJet CP2020", ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT01'))
$strPrinter = 2, "Brother DCP-8065DN", ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT02'))
$strPrinter = 3, "Canon iR-ADV C2220/2230", ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT03'))
$strPrinter = 4, "HP LJ300-400 color M351-M451", ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\PS\PT04'))
$x
There are two problems with your current script.
The first one, that $x appears empty is due to a scoping issue. When inside the scope of the add_Click() event handler, $x is a local variable and its value won't be accessible outside of the event handler.
You could work around this by specifying a parent scope, like (notice the global: scope qualifier):
$global:x = $objListBox.SelectedItem
But still, nothing would happen, leading me to the second issue:
I'm not sure what you mean by "string setup", but your script basically ends up setting the last printer as the default whenever it runs.
You'll want to define the printers up front, before showing the dialog, and wrap the ((New-Object... statements in a scriptblock, something like:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# New array of "printer objects", rather than $strPrinter
$Printers = #(
New-Object psobject -Property #{
Name = "HP Color LaserJet CP2020"
SetCommand = { ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT01')) }
},
New-Object psobject -Property #{
Name = "Brother DCP-8065DN"
SetCommand = { ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT02')) }
},
New-Object psobject -Property #{
Name = "Canon iR-ADV C2220/2230"
SetCommand = { ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\\PS\PT03')) }
},
New-Object psobject -Property #{
Name = "HP LJ300-400 color M351-M451"
SetCommand = { ((New-Object -ComObject WScript.Network).SetDefaultPrinter('\PS\PT04')) }
}
)
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a Printer"
$objForm.Size = New-Object System.Drawing.Size(400,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$x=$objListBox.SelectedItem;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$objForm.Close()}})
#Ok Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({
# Grab the printer array index
$index = $objListBox.SelectedIndex
# Execute the appropriate command
& $Printers[$index].SetCommand
# Exit
$objForm.Close()
})
$objForm.Controls.Add($OKButton)
#Cancel Button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please select a printer:"
$objForm.Controls.Add($objLabel)
#List box showing printer options
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(360,20)
$objListBox.Height = 80
foreach($Printer in $Printers){
[void] $objListBox.Items.Add($Printer.Name)
}
$objForm.Controls.Add($objListBox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
Since the printers are now added to the listbox in correct order, we can simply use the SelectedIndex property to find the original printer object and invoke the scriptblock that sets it as default

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.