如果 PowerShell 脚本终止则执行代码
Execute code if a PowerShell script is terminated
如果PowerShell脚本被强制终止,是否可以强制执行某些代码?我试过 try..finally 和 Traps,但它们似乎都不起作用,至少当我从 PowerShell ISE 中按 Ctrl-C 时是这样。
基本上,我有一个执行 PowerShell 脚本的 Jenkins 构建。如果出于任何原因我想从 Jenkins 中停止构建,我不希望任何子进程锁定文件,因此使我的构建项目处于中断状态,直到管理员手动终止有问题的进程(nunit-agent.exe
in我的情况)。因此,如果发生这种情况,我希望能够强制执行终止 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.
我为此使用 try {} finally {}
。 finally-block 运行s 当 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"
}
更新:finally 块将无法用于输出,因为管道在 CTRL+C 上停止。
Note that pressing CTRL+C stops the pipeline. Objects that are sent to
the pipeline will not be displayed as output. Therefore, if you
include a statement to be displayed, such as "Finally block has run",
it will not be displayed after you press CTRL+C, even if the Finally
block ran.
但是,如果将 Receive-Job
的输出保存到 $global:content = Receive-Job $sleepJob
之类的全局变量中,则可以在 finally 块之后读取它。该变量通常在不同的本地范围内创建并在 finally 块之后丢失。
如果PowerShell脚本被强制终止,是否可以强制执行某些代码?我试过 try..finally 和 Traps,但它们似乎都不起作用,至少当我从 PowerShell ISE 中按 Ctrl-C 时是这样。
基本上,我有一个执行 PowerShell 脚本的 Jenkins 构建。如果出于任何原因我想从 Jenkins 中停止构建,我不希望任何子进程锁定文件,因此使我的构建项目处于中断状态,直到管理员手动终止有问题的进程(nunit-agent.exe
in我的情况)。因此,如果发生这种情况,我希望能够强制执行终止 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.
我为此使用 try {} finally {}
。 finally-block 运行s 当 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"
}
更新:finally 块将无法用于输出,因为管道在 CTRL+C 上停止。
Note that pressing CTRL+C stops the pipeline. Objects that are sent to the pipeline will not be displayed as output. Therefore, if you include a statement to be displayed, such as "Finally block has run", it will not be displayed after you press CTRL+C, even if the Finally block ran.
但是,如果将 Receive-Job
的输出保存到 $global:content = Receive-Job $sleepJob
之类的全局变量中,则可以在 finally 块之后读取它。该变量通常在不同的本地范围内创建并在 finally 块之后丢失。