Powershell 处理键盘中断,执行结束块

Powershell 处理键盘中断,执行结束块,powershell,Powershell,我有一个powershell函数,用于处理文件列表。我使用开始、过程和结束块来执行以下操作: begin { # prepate some stuff } process { # process each file } end { # clean up } 现在,当我点击Ctrl+C时,整个脚本就在它所在的位置终止。对于流程部分来说,这并不是一个真正的问题,因为这只会对最后一个命令进行永久性更改 但是,我仍然希望执行end块中的内容来稍微清理一下,并打印一些关于成功处理

我有一个powershell函数,用于处理文件列表。我使用
开始
过程
结束
块来执行以下操作:

begin {
    # prepate some stuff
}
process {
    # process each file
}
end {
    # clean up
}
现在,当我点击Ctrl+C时,整个脚本就在它所在的位置终止。对于流程部分来说,这并不是一个真正的问题,因为这只会对最后一个命令进行永久性更改

但是,我仍然希望执行
end
块中的内容来稍微清理一下,并打印一些关于成功处理的文件的统计信息


是否有一种干净的方法可以捕获键盘中断,同时保持开始/进程/结束结构?

一种方法是在脚本块运行时禁用Ctrl-C作为中断处理。当然,您必须手动检查它是否会中断,但它应该保证结束块运行

begin { 
  [Console]::TreatControlCAsInput = $true
}
process {
  # Maybe check for Ctrl-C here to terminate processing
}
end { 
  [Console]::TreatControlCAsInput = $false
}
为了以非阻塞方式检查Ctr-C作为输入,您可以执行以下操作

if ([Console]::KeyAvailable) {
  $key = [Console]::ReadKey($true)
  if ($key.key -eq "C" -and $key.modifiers -eq "Control") { 
    # Clean up and exit
  }
}
当脚本因以下任何条件终止时,try/catch/finally块集的“finally”部分仍将执行:

  • 按下Ctrl+C(在任何时候)
  • 在catch部分中遇到Exit关键字
  • 发生致命错误(在“最终”部分之外)
把你所有的清理工作都放在那里。无论发生什么情况,它都将运行(编辑:除非“finally”块本身抛出错误)

(进一步编辑:我将原始标记保留在那里以供空间参考——它们现在已被删除,因此文字复制/粘贴不应包含无效关键字

try { # begin, and/or process
}
catch { # optionally handle errors
}
finally { # clean up 
}

您可以将准备步骤和实际处理全部放在一个“try”块中,或者您可以创建其中两个块——无论哪种方式,“try”和“catch”都是必需的,“finally”是可选的。

Hmm,很有趣。您是否可以扩展“可能在此处检查Ctrl-C以终止处理”部分?如果Ctrl-C被视为输入,我如何在内部检查它?我如何停止处理而不抛出错误(这也会跳过结束块或不跳过结束块)?@poke我添加了一些示例代码,以检查是否有
ctr-c
作为输入。至于结束块,可能最好的解决方案是将结束块处理分解为另一个函数。然后,如果在
进程
块中按下
ctr-c
,则可以直接调用它并退出循环,并通过
end无条件地调用它
如果这样做能起作用那就太好了,但它似乎不是有效的语法。我遇到一个错误,
end
无法识别;我不认为
begin/process/finally
可能包含在任何内容中,因为使用
begin
已经抛出了一个错误,导致立即执行
catch
。Cla验证了答案,以便可以复制/粘贴。我知道正常的异常处理是如何工作的。但这并不能使处理管道的能力…