代码之家  ›  专栏  ›  技术社区  ›  Rafid

如果PowerShell脚本终止,则执行代码

  •  1
  • Rafid  · 技术社区  · 10 年前

    如果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.
    
    1 回复  |  直到 10 年前
        1
  •  2
  •   Frode F.    10 年前

    我使用 try {} finally {} 为此。finally块在try完成或使用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块之后丢失。

    推荐文章