When the script is executing the Read-Host
cmdlet, closing the window does not activate the finally
block. Below is an arbitrary but minimally functional example. I'm using PowerShell 5.0. The Beep() is just to make it obvious the finally block executes.
try {
$value= Read-Host -Prompt "Input"
sleep 5
} finally {
[Console]::Beep(880,1000)
}
Read-Host
the finally
block will NOT execute.sleep
the
finally
block WILL execute.finally
block WILL execute.Is there something fundamental I'm missing about why the finally
block is NOT executing when closing the window during a Read-Host
?
The full case involves starting a service on an Amazon Snowball device and needing to stop the service if the script is closed. The full case behavior mirrors the example case above.
EDIT: Changed variable from $input to $value due to comments saying $input is a reserved variable. Does not change behavior.
Continuing from my comment.
The console host is a bit inflexible based on what you are doing natively from it. That 'X' has to do with the PowerShell session/process, not the code running in it. Hence why CRTL+C works, as you are stopping the code run, not the PowerShell session/process.
Here are a couple of approaches to get you thinking about your options.
###############################################################################
#region Begin initialize environment #
###############################################################################
# Initialize GUI resources
Add-Type -AssemblyName System.Drawing,
PresentationCore,
PresentationFramework,
System.Windows.Forms,
microsoft.VisualBasic
[System.Windows.Forms.Application]::EnableVisualStyles()
###############################################################################
#endregion End initialize environment #
###############################################################################
# Prevent the MessageBox UI from closing until an entry is made
while (
($UserEntry = [Microsoft.VisualBasic.Interaction]::
InputBox('Enter a Host/User', 'Add Item')) -eq ''
)
{
[System.Windows.Forms.MessageBox]::
Show(
'Entry cannot be empty',
"Error on close" ,
0,
[System.Windows.MessageBoxImage]::Error
)
}
"You entered $UserEntry"
Or a full custom form for more granular control
# Initialize the form object
$form = New-Object System.Windows.Forms.Form
# Define form elements
$form.Text = 'Data Entry'
$txtUserInput = New-Object system.Windows.Forms.TextBox
$txtUserInput.multiline = $false
$txtUserInput.width = 120
$txtUserInput.height = 20
$txtUserInput.location = New-Object System.Drawing.Point(40,29)
$txtUserInput.Font = 'Microsoft Sans Serif,10'
$form.controls.AddRange(@(
$txtUserInput
)
)
# Evaluate form events
$form.Add_Closing(
{
param
(
$Sender,$Event
)
$result = [System.Windows.Forms.MessageBox]::Show(
'Are you sure you want to exit?',
'Close',
[System.Windows.Forms.MessageBoxButtons]::YesNo
)
if ($result -ne [System.Windows.Forms.DialogResult]::Yes)
{$Event.Cancel = $true}
})
# Start the form
$form.ShowDialog() | Out-Null
# Resource disposal
$form.Dispose()