I am trying to write a PowerShell script that lets the user select a printer. The script below displays a menu of printers, but I can't figure out how to get the $selectPrinter variable out of the scope of the button.Add_Click block and into the rest of the script. This is probably easy for experts, but none of my experiments work. Is there an obvious answer that I'm missing? Here is the code:
# Load Windows Forms and drawing libraries
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Printer'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
# Add a label
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,10)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please select a printer:'
$form.Controls.Add($label)
# Add a list box
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,40)
$listBox.Size = New-Object System.Drawing.Size(260,100)
$form.Controls.Add($listBox)
# Populate the list box with printer names
$printers = Get-Printer | Select-Object -ExpandProperty Name
foreach ($printer in $printers) {
$listBox.Items.Add($printer)
}
# Add a button
$button = New-Object System.Windows.Forms.Button
$button.Location = New-Object System.Drawing.Point(10,150)
$button.Size = New-Object System.Drawing.Size(100,20)
$button.Text = 'OK'
$form.Controls.Add($button)
# Add button click event
$button.Add_Click({
$selectedPrinter = $listBox.SelectedItem
$form.Close()
})
# Show the form
$form.Add_Shown({$form.Activate()})
[void] $form.ShowDialog()
# Output the selected printer
if ($selectedPrinter) {
Write-Host "Selected printer: $selectedPrinter"
} else {
Write-Host "No printer selected."
}
pause
$script:variable = ...; without that, you'll implicitly create a block-local variable. See the linked duplicate for details.$global:or$script:part of the variable only worked in the child scope, and that I didn't need it outside the child scope. At least I think that's what is the case...$script:is optional - but$global:is best avoided, because it affects the entire session, not just your script. More generally, the fact that the event-handler script block runs in a child scope means that if you want to target the caller's scope - which may or may not be the script scope - you needSet-Variable -Scope 1 ..., as discussed in the duplicate.