powershell add action to combobox - powershell

at the moment, i want to build a powershell gui. the form is running fine, so there are no problems. now i want to add an event for my selection, for example starting another script choosing "item1" and another script choosing "item2" and so on. how can i achieve that? thanfs for any help.
This is what i have actually.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Combobox"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{
foreach ($objItem in $objCombobox.SelectedItem)
{$x += $objItem}
$objForm.Close()
}
})
$objForm.Add_KeyDown({if ($_.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(
{
foreach ($objItem in $objCombobox.SelectedItem)
{$x += $objItem}
$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 choose"
$objForm.Controls.Add($objLabel)
$objCombobox = New-Object System.Windows.Forms.Combobox
$objCombobox.Location = New-Object System.Drawing.Size(10,40)
$objCombobox.Size = New-Object System.Drawing.Size(260,20)
[void] $objCombobox.Items.Add("Item 1")
[void] $objCombobox.Items.Add("Item 2")
[void] $objCombobox.Items.Add("Item 3")
[void] $objCombobox.Items.Add("Item 4")
[void] $objCombobox.Items.Add("Item 5")
$objCombobox.Height = 70
$objForm.Controls.Add($objCombobox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
$x

Continuing on my comment, below the revised script
$x = # the return variable which is updated in the OK Click event
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Combobox"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$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.DialogResult = [System.Windows.Forms.DialogResult]::OK
$OKButton.Add_Click({
$script:x = $objCombobox.SelectedItem # there is only one SelectedItem
$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.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$objForm.Controls.Add($CancelButton)
# using this, you do not need the Add_KeyDown events to react on clicking the OK or Cancel button
$objForm.AcceptButton = $OKButton
$objForm.CancelButton = $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 choose"
$objForm.Controls.Add($objLabel)
$objCombobox = New-Object System.Windows.Forms.Combobox
$objCombobox.Location = New-Object System.Drawing.Size(10,40)
$objCombobox.Size = New-Object System.Drawing.Size(260,20)
$objCombobox.Height = 70
[void] $objCombobox.Items.Add("Item 1")
[void] $objCombobox.Items.Add("Item 2")
[void] $objCombobox.Items.Add("Item 3")
[void] $objCombobox.Items.Add("Item 4")
[void] $objCombobox.Items.Add("Item 5")
$objCombobox.Add_SelectedIndexChanged({
# for demo, just write to console
Write-Host "You have selected '$($this.SelectedItem)'" -ForegroundColor Cyan
# inside here, you can refer to the $objCombobox as $this
switch ($this.SelectedItem) {
"Item 1" { <# do something when Item 1 is selected #> }
"Item 2" { <# do something when Item 2 is selected #> }
"Item 3" { <# do something when Item 3 is selected #> }
"Item 4" { <# do something when Item 4 is selected #> }
"Item 5" { <# do something when Item 5 is selected #> }
}
})
$objForm.Controls.Add($objCombobox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
# IMPORTANT clean up the form when done
$objForm.Dispose()
$x
As you can see, I have removed both $objForm.Add_KeyDown() event handlers, as they are not needed when you set $objForm.AcceptButton = $OKButton and $objForm.CancelButton = $CancelButton. Also, always remove the form from memory when done with it using $objForm.Dispose()
As per your comment, I understand you want to perform the selected action only after closing the form.
In that case also remove the $OKButton.Add_Click() event handler and just store the selected option in $script:x in the SelectedIndexChanged event:
$x = # the return variable which is updated in the SelectedIndexChanged event handler
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Combobox"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Topmost = $True
$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.DialogResult = [System.Windows.Forms.DialogResult]::OK
$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.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$objForm.Controls.Add($CancelButton)
# using this, you do not need the Add_KeyDown events to react on clicking the OK or Cancel button
$objForm.AcceptButton = $OKButton
$objForm.CancelButton = $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 choose"
$objForm.Controls.Add($objLabel)
$objCombobox = New-Object System.Windows.Forms.Combobox
$objCombobox.Location = New-Object System.Drawing.Size(10,40)
$objCombobox.Size = New-Object System.Drawing.Size(260,20)
$objCombobox.Height = 70
[void] $objCombobox.Items.Add("Item 1")
[void] $objCombobox.Items.Add("Item 2")
[void] $objCombobox.Items.Add("Item 3")
[void] $objCombobox.Items.Add("Item 4")
[void] $objCombobox.Items.Add("Item 5")
$objCombobox.Add_SelectedIndexChanged({
# inside here, you can refer to the $objCombobox as $this
# set the return variable to the SelectedItem
$script:x = $this.SelectedItem # there is only one SelectedItem
# or, if you want it to, you can start the action here immediately without leaving the form:
# switch ($this.SelectedItem) {
# "Item 1" { <# do something when Item 1 is selected #> }
# "Item 2" { <# do something when Item 2 is selected #> }
# "Item 3" { <# do something when Item 3 is selected #> }
# "Item 4" { <# do something when Item 4 is selected #> }
# "Item 5" { <# do something when Item 5 is selected #> }
# }
})
$objForm.Controls.Add($objCombobox)
$objForm.Add_Shown({$objForm.Activate()})
$dialogResult = $objForm.ShowDialog()
# IMPORTANT clean up the form when done
$objForm.Dispose()
if ($dialogResult -eq 'OK' -and ![string]::IsNullOrWhiteSpace($x)) {
# the form was not cancelled and a selection was made
# for demo, just write to console
Write-Host "You have selected '$($x)'" -ForegroundColor Cyan
switch ($x) {
"Item 1" { <# do something when Item 1 is selected #> }
"Item 2" { <# do something when Item 2 is selected #> }
"Item 3" { <# do something when Item 3 is selected #> }
"Item 4" { <# do something when Item 4 is selected #> }
"Item 5" { <# do something when Item 5 is selected #> }
}
}
else {
Write-Host "You have cancelled the dialog or did not select anything"
}
Ok, apparently now you want the form to stay after making a choice and clicking the OK button (and thus perform the chosen action).
In that case, you can simplify like this:
$x = #() # the return variable (an array with all selections made in order)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Combobox"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Topmost = $True
$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({
$selected = $objCombobox.SelectedItem
$script:x += $objCombobox.SelectedItem
if (![string]::IsNullOrWhiteSpace($selected)) {
Write-Host "Performing action $($selected)" -ForegroundColor Yellow
$objLabel.Text = "Performing action $($selected)"
switch ($selected) {
"Item 1" { <# do something when Item 1 is selected #> }
"Item 2" { <# do something when Item 2 is selected #> }
"Item 3" { <# do something when Item 3 is selected #> }
"Item 4" { <# do something when Item 4 is selected #> }
"Item 5" { <# do something when Item 5 is selected #> }
}
$objLabel.Text = "Please choose"
$objCombobox.SelectedIndex = -1 # reset the combobox to blank
}
})
$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.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$objForm.Controls.Add($CancelButton)
# using this, you do not need the Add_KeyDown events to react on clicking the OK or Cancel button
$objForm.AcceptButton = $OKButton
$objForm.CancelButton = $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 choose"
$objForm.Controls.Add($objLabel)
$objCombobox = New-Object System.Windows.Forms.Combobox
$objCombobox.Location = New-Object System.Drawing.Size(10,40)
$objCombobox.Size = New-Object System.Drawing.Size(260,20)
$objCombobox.Height = 70
[void] $objCombobox.Items.Add("Item 1")
[void] $objCombobox.Items.Add("Item 2")
[void] $objCombobox.Items.Add("Item 3")
[void] $objCombobox.Items.Add("Item 4")
[void] $objCombobox.Items.Add("Item 5")
$objForm.Controls.Add($objCombobox)
$objForm.Add_Shown({$objForm.Activate()})
$dialogResult = $objForm.ShowDialog()
# IMPORTANT clean up the form when done
$objForm.Dispose()
if ($dialogResult -ne 'Cancel' -or $x.Count -eq 0) {
# the form was cancelled or no selection was made
# for demo, just write to console
Write-Host "You have cancelled the dialog or did not select anything.."
}
else {
Write-Host "The selection(s) you made were $($x -join ', ')" -ForegroundColor Cyan
}

Related

How to Add a BIOS version and computer model name using a System.Windows.Forms.Form - PowerShell

I'm new to powershell and I would like to know if is possible to add BIOS version and Laptop/Desktop model name on a Multiple-selection list boxes on PowerShell.
This is an image of the script interface.
I started building this script with this link:
https://learn.microsoft.com/en-us/powershell/scripting/samples/multiple-selection-list-boxes?source=recommendations&view=powershell-7.3
And add some features visiting another sites, but ain't found one code that help me to show this info on form (and i don't know if this is possible)
I do not finish the script yet, but the goal with this script will help me to install multiple software and learn more about PowerShell
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = $env:COMPUTERNAME
$form.Size = New-Object System.Drawing.Size(450,400)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(130,230)
$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(230,230)
$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(80,50)
$label.Size = New-Object System.Drawing.Size(300,50)
$label.Text = 'Please select Software or BIOS:'
$form.Controls.Add($label)
$label.Font = New-Object System.Drawing.Font("Arial",11,[System.Drawing.FontStyle]::Regular)
$label2 = New-Object System.Windows.Forms.Label
$label2.Location = New-Object System.Drawing.Point(90,10)
$label2.Size = New-Object System.Drawing.Size(250,30)
$label2.Text = 'Bios'
$form.Controls.Add($label2)
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(70,100)
$listBox.Size = New-Object System.Drawing.Size(290,80)
$listBox.Height = 125
$listBox.Font = New-Object System.Drawing.Font("Arial",12,[System.Drawing.FontStyle]::Regular)
[void] $listBox.Items.Add('All W10-BR')
[void] $listBox.Items.Add('All W10-ES')
[void] $listBox.Items.Add('All W11-BR')
[void] $listBox.Items.Add('All W11-ES')
[void] $listBox.Items.Add('Open Text-10.5')
[void] $listBox.Items.Add('Fuze-22.06.24445')
[void] $listBox.Items.Add('VLC-3.0.18')
[void] $listBox.Items.Add('Five9')
[void] $listBox.Items.Add('CitrixWorkspaceApp-2212')
[void] $listBox.Items.Add('W11-KB5022303-22H2-22621.1105')
[void] $listBox.Items.Add('W10-KB5022282-22H2-19045.2486')
[void] $listBox.Items.Add('Office LangPack Pt-br2013.exe')
[void] $listBox.Items.Add('Office LangPack ES.exe')
[void] $listBox.Items.Add('Latitude')
[void] $listBox.Items.Add('Latitude')
[void] $listBox.Items.Add('Latitude')
$listBox.Add_SelectedIndexChanged({
# inside here, you can refer to the $$listBox as $this
# set the return variable to the SelectedItem
$script:x = $this.SelectedItem # there is only one SelectedItem
# or, if you want it to, you can start the action here immediately without leaving the form:
# switch ($this.SelectedItem) {
# "Item 1" { <# do something when Item 1 is selected #> }
# "Item 2" { <# do something when Item 2 is selected #> }
# "Item 3" { <# do something when Item 3 is selected #> }
# "Item 4" { <# do something when Item 4 is selected #> }
# "Item 5" { <# do something when Item 5 is selected #> }
# }
})
$form.Controls.Add($listBox)
$Form.Add_Shown({$Form.Activate()})
$dialogResult = $Form.ShowDialog()
$Form.Dispose()
if ($dialogResult -ne 'Cancel' -or $x.Count -eq 0) {
switch ($x){
"All W10-BR" {Start-Process "C:\Users\dvd87592\Desktop\Pacote de Instalação\5-CitrixWorkspaceApp-2212.exe" /passive -Wait
Start-Process "C:\Users\dvd87592\Desktop\Pacote de Instalação\3-VLC-3.0.18.msi" /passive}
"Fuze-22.06.24445" {Start-Process "C:\Users\dvd87592\Desktop\Pacote de Instalação\2-Fuze-22.06.24445.msi" /passive -wait}
"VLC-3.0.18" { Start-Process "C:\Users\dvd87592\Desktop\Pacote de Instalação\2-VLC-3.0.18.msi" /passive -wait}
"CitrixWorkspaceApp-2212" { Start-Process "C:\Users\dvd87592\Desktop\Pacote de Instalação\3-CitrixWorkspaceApp-2212.exe" /silent }
}
}
I checked other sites and forums and tried a few commands but doesn't work.

Show popup message with auto close and on top of all of the windows

I need to create a function that shows a message to the user and if the user doesn't respond then it automatically closes the windows.
function ShowMsg ($timeout,$message)
{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(200,40)
$form.Controls.Add($label)
#add button to form
$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)
$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()
}
$timeout = 30
ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout
$r = ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout
if ($r -eq [System.Windows.Forms.DialogResult]::OK)
{
Write-Host “Press ok now”
}else{
Write-Host "$r"
}
I try to use the above code but after showing the message 3 or 4 times it starts closing the popup and in the output, I see "cancel"
enter image description here
The problem is with the timer.
In the form declaration, where you create the timer object, initially set it to $timer.Enabled = $false.
Next, add a $form.Add_Shown({$timer.Enabled = $true; $timer.Start()}) event handler to start the timer when the form is first shown.
In the Tick event of the timer, tell it to Stop() and close the form.
Don't forget to dispose of the timer aswell:
Try
function ShowMsg ([int]$timeout, [string]$message){
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
$form.Topmost = $true
$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Location = New-Object System.Drawing.Point(10,10)
$label.Size = New-Object System.Drawing.Size(200,40)
$form.Controls.Add($label)
#add button to form
$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.Controls.Add($okButton)
$form.AcceptButton = $okButton
$timer = New-Object System.Windows.Forms.Timer
$timer.Enabled = $false # disabled at first
$timer.Interval = $timeout * 1000
$timer.Add_Tick({ $timer.Stop(); $form.Close() })
# start the timer as soon as the form is shown
$form.Add_Shown({$timer.Enabled = $true; $timer.Start()})
$form.ShowDialog()
# clean-up
$timer.Dispose()
$form.Dispose()
}

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

Do textbox while variable is empty in powershell

I'm new to powershell and I need some help with a script.
I have a simple code which loops while the user doesn't type a name :
do {$name = Read-Host "Choose a name "}
while (!$name) {}
I try to use it for the GUI version but the loop doesn't stop :
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$box = {
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Hostname"
$Form.Size = New-Object System.Drawing.Size(270,150)
$Form.StartPosition = "CenterScreen"
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(165,75)
$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)
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Size(10,15)
$Label.Size = New-Object System.Drawing.Size(280,20)
$Label.Text = "Choose a name :"
$Form.Controls.Add($Label)
$TextBox = New-Object System.Windows.Forms.TextBox
$TextBox.Location = New-Object System.Drawing.Size(10,40)
$TextBox.Size = New-Object System.Drawing.Size(230,20)
$Form.Controls.Add($TextBox)
$Form.Topmost = $True
$Form.Add_Shown({$TextBox.Select()})
$result = $Form.ShowDialog()
return $TextBox.Text
}
do {&$box}
while (!$TextBox.Text) {}
I think I'm missing something, but I don't know what...
Sorry for my poor english, thanks in advance.
Your textbox, being invoked, is never transmitted to its parent. Therefore, you need to assign your return value and works from there.
do {$value = &$box }
while ([String]::IsNullOrWhiteSpace($value))
Write-Host $value -ForegroundColor Cyan
Try this out.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# Null out name value in case you need to call the script multiple times in the same PS session.
$name = $null
$box = {
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Hostname"
$Form.Size = New-Object System.Drawing.Size(270,150)
$Form.StartPosition = "CenterScreen"
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(165,75)
$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)
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Size(10,15)
$Label.Size = New-Object System.Drawing.Size(280,20)
$Label.Text = "Choose a name :"
$Form.Controls.Add($Label)
$TextBox = New-Object System.Windows.Forms.TextBox
$TextBox.Location = New-Object System.Drawing.Size(10,40)
$TextBox.Size = New-Object System.Drawing.Size(230,20)
$Form.Controls.Add($TextBox)
$Form.Topmost = $True
$Form.Add_Shown({$TextBox.Select()})
$result = $Form.ShowDialog()
# Only return if the TextBox.Text is set to stop it from exiting immediately after rendering the form.
if ($TextBox.Text) {return $TextBox.Text}
}
# While the name variable is null, show the form again.
while (-not $name) {
$name = & $box
}

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