Powershell 尝试抓住。。在主机读取过程中最终失败

Powershell 尝试抓住。。在主机读取过程中最终失败,powershell,try-catch-finally,read-host,Powershell,Try Catch Finally,Read Host,脚本执行读取主机cmdlet时,关闭窗口不会激活最终块。下面是一个任意但功能最少的示例。我正在使用PowerShell 5.0。Beep()只是为了使finally块的执行变得明显 try { $value= Read-Host -Prompt "Input" sleep 5 } finally { [Console]::Beep(880,1000) } 如果在读取主机时单击红色X关闭窗口 finally块将不执行 如果在睡眠期间单击红色X关闭窗口,

脚本执行
读取主机
cmdlet时,关闭窗口不会激活
最终
块。下面是一个任意但功能最少的示例。我正在使用PowerShell 5.0。Beep()只是为了使finally块的执行变得明显

try {
    $value= Read-Host -Prompt "Input"
    sleep 5
} finally {
    [Console]::Beep(880,1000)
}
  • 如果在读取主机时单击红色X关闭窗口
    finally
    块将不执行
  • 如果在
    睡眠期间单击红色X关闭窗口,则
    
    最后将执行
  • 如果在任意点使用Ctrl-C中断,则将执行
    finally
  • 读取主机
    期间关闭窗口时,为什么没有执行
    finally
    块,我是否缺少一些基本信息

    完整案例涉及在Amazon Snowball设备上启动服务,如果脚本关闭,则需要停止服务。完整案例行为反映了上述示例案例


    编辑:由于注释说$input是保留变量,所以将变量从$input更改为$value。不会改变行为。

    继续我的评论

    控制台主机有点不灵活,这取决于您在主机上执行的操作。“X”与PowerShell会话/进程有关,而不是其中运行的代码。因此,当您停止代码运行而不是PowerShell会话/进程时,CRTL+C可以工作

    这里有几种方法可以让你思考你的选择

    ###############################################################################
    #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"
    
    或一个完整的自定义表单,以实现更精细的控制

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

    [1]
    $Input
    是一个保留的自动变量。除非你完全确定自己了解副作用,否则不要写信给它。[grin][2]你可能看到了“主持人”和各种时尚流互动的结果。我假设在控制台直接操作中终止控制台会完全绕过powershell。[1]我更新了代码段,使其没有$input。即使使用不同的变量,行为也是相同的。[2] 我相信这是有区别的。奇怪的是在
    睡眠期间关闭控制台窗口
    确实激活了
    最终
    。这可能是因为您不再直接在主机中操作。。。您又回到了PoSh。在这种情况下,有没有办法执行
    finally
    块?我想运行一些清理代码,即使用户只是关闭了窗口。CRTL+C意味着停止运行代码并返回提示符。”X“,表示立即退出会话。如果用户关闭“x”以关闭控制台窗口框,并且不响应读取主机,则无论您做什么,都不会发生代码。不管你使用哪种语言。执行此操作的唯一方法是创建自己的表单以收集用户信息,并且可以在表单关闭/处置事件上采取操作。您可以禁用表单中的“X”,并强制使用关闭按钮,从而触发该表单的代码。