【问题标题】:Execute code if a PowerShell script is terminated如果 PowerShell 脚本终止,则执行代码
【发布时间】:2016-02-16 04:42:47
【问题描述】:

如果强制终止 PowerShell 脚本,是否可以强制执行某些代码?我试过 try..finally 和 Traps,但它们似乎都不起作用,至少当我从 PowerShell ISE 中按 Ctrl-C 时。

基本上,我有一个执行 PowerShell 脚本的 Jenkins 构建。如果出于任何原因我想从 Jenkins 中停止构建,我不希望任何子进程锁定文件,从而使我的构建项目处于损坏状态,直到管理员手动终止有问题的进程(在我的情况下为 nunit-agent.exe )。因此,如果发生这种情况,我希望能够强制执行终止 nunit-agent.exe 的代码。

更新:正如@Frode 下面建议的那样,我尝试使用try..finally

$sleep = {
  try {
    Write-Output "In the try block of the job."
    Start-Sleep -Seconds 10
  }
  finally {
    Write-Output "In the finally block of the job."
  }
}

try {
  $sleepJob = Start-Job -ScriptBlock $sleep
  Start-Sleep -Seconds 5
}
finally {
  Write-Output "In the finaly block of the script."
  Stop-Job $sleepJob
  Write-Output "Receiving the output from the job:"
  $content = Receive-Job $sleepJob
  Write-Output $content
}

然后,当我执行此操作并使用 Ctrl-C 中断该过程时,我没有得到任何输出。我认为我应该得到的是:

In the finally block of the script.
Receiving the output from the job:
In the try block of the job.
In the finally block of the job.

【问题讨论】:

    标签: powershell nunit powershell-ise


    【解决方案1】:

    我为此使用try {} finally {}。 finally 块在尝试完成或使用 ctrl+c 时运行,因此您需要运行可以安全运行的命令,例如。如果你杀死一个已经死的进程也没关系..

    或者您可以使用$? 添加测试以查看最后一个命令是否成功,例如:

    try {
        Write-Host "Working"
        Start-Sleep -Seconds 100
    
    } finally {
        if(-not $?) { Write-Host "Cleanup on aisle 5" }
        Write-Host "Done"
    }
    

    或者创建你自己的测试(以防 try 中的最后一个命令由于某种原因失败):

    try {
        $IsDone = $false
        Write-Host "Working"
        Start-Sleep -Seconds 100
        #.....
        $IsDone = $true
    
    } finally {
        if(-not $IsDone) { Write-Host "Cleanup on aisle 5" }
        Write-Host "Done"
    }
    

    更新:由于管道在 CTRL+C 上停止,finally 块将无法用于输出。

    请注意,按 CTRL+C 会停止管道。发送到的对象 管道不会显示为输出。因此,如果你 包括要显示的语句,例如“Finally block has run”, 按 CTRL+C 后它不会显示,即使最后 块跑了。

    来源:about_Try_Catch_Finally

    但是,如果您将 Receive-Job 的输出保存到像 $global:content = Receive-Job $sleepJob 这样的全局变量中,您可以在 finally 块之后读取它。该变量通常在不同的本地范围内创建,并在 finally-block 之后丢失。

    【讨论】:

    • 谢谢@Frode。我试过了,但没有用。请参阅上面的编辑。
    • 哦,我明白了,现在说得通了,也让我很开心 :) 那么与主进程通信的推荐方式是什么?基本上,从子流程来看,我想说的是构建已停止,因此我们正在终止 NUnit 测试,因此我们可以从 Jenkins 服务器告诉发生了什么。
    • atm 看不到太多选项。我会写入日志文件或使用退出代码。前任。让你的 finally 块以exit 1234 结束。
    • 谢谢。是的,我正在考虑使用日志文件并将其从主脚本中转储。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2020-10-09
    • 2016-12-28
    • 2016-12-01
    • 1970-01-01
    • 2011-01-02
    • 2018-04-24
    相关资源
    最近更新 更多