【发布时间】:2010-12-15 04:56:08
【问题描述】:
如何在 PowerShell 脚本中捕获和处理 Ctrl+C?我知道我可以从 v2 中的 cmdlet 执行此操作,方法是包含 Powershell.Stop() 方法的覆盖,但我找不到在脚本中使用的模拟。
我目前正在执行清理via an end block,但是当脚本被取消时我需要执行额外的工作(而不是运行到完成)。
【问题讨论】:
如何在 PowerShell 脚本中捕获和处理 Ctrl+C?我知道我可以从 v2 中的 cmdlet 执行此操作,方法是包含 Powershell.Stop() 方法的覆盖,但我找不到在脚本中使用的模拟。
我目前正在执行清理via an end block,但是当脚本被取消时我需要执行额外的工作(而不是运行到完成)。
【问题讨论】:
您可以使用here on PoshCode中描述的方法
总结:
设置
[console]::TreatControlCAsInput = $true
然后使用
轮询用户输入if($Host.UI.RawUI.KeyAvailable -and (3 -eq
[int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,NoEcho").Character))
【讨论】:
try-catch-finally 的 documentation 说:
即使您使用 CTRL+C 停止脚本,Finally 块也会运行。最后 如果 Exit 关键字从 Catch 中停止脚本,块也会运行 块。
请参阅以下示例。运行它并按ctrl-c 取消它。
try
{
while($true)
{
"Working.."
Start-Sleep -Seconds 1
}
}
finally
{
write-host "Ended work."
}
【讨论】:
try 的末尾设置$didcomplete = $true 并在finally 内使用if ($didcomplete) { Write-Host "Ended work." } 进行检查
$PSCmdlet 上还有一个 Stopping 属性可用于此目的。
【讨论】:
Stopping 是 false,即使在按 PowerShell/PowerShell#6322 停止时也是如此。
这是最近的工作解决方案。我在需要控制执行中断(关闭文件句柄)的循环中使用 if 部分。
[Console]::TreatControlCAsInput = $true # at beginning of script
if ([Console]::KeyAvailable){
$readkey = [Console]::ReadKey($true)
if ($readkey.Modifiers -eq "Control" -and $readkey.Key -eq "C"){
# tasks before exit here...
return
}
}
另请注意,有一个错误导致 KeyAvailable 在脚本启动时为真。您可以通过在开始时读取调用 ReadKey 来缓解。这种方法不需要,只是在这种情况下值得了解。
【讨论】: