启动过程后作业脚本块中的代码不执行

时间:2017-08-18 20:06:41

标签: powershell jobs

当我使用PowerShell 5.1创建自动化脚本时,我遇到了一个问题 - 在作业的脚本块中,Start-Process之后的代码将无法执行。这是一个简单的复制品:

步骤1>>为Start-Process准备一个.cmd文件,callee.cmd中的代码是:

@echo off
echo "Callee is executing ..."
exit /B 0

第2步>>准备PowerShell代码

$scriptBlock = {
    $res = Start-Process -FilePath "cmd.exe" -Wait -PassThru -NoNewWindow -ArgumentList "/c .\callee.cmd"
    throw "ERROR!"
}

$job = Start-Job -ScriptBlock $scriptBlock
Wait-Job $job
Receive-Job $job
Write-Host($job.State)

步骤3>>运行PowerShell脚本,屏幕上的输出为:

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      Job1            BackgroundJob   Completed     True            localhost            ...
Completed

预期值应为“失败”。 我的代码是否有问题或我以错误的方式使用作业?

2 个答案:

答案 0 :(得分:3)

Start-Job在所谓的服务器模式中的单独PowerShell进程中运行作业。在此模式下,PowerShell作业进程使用标准输入和输出流与父进程交换消息。

-NoNewWindow cmdlet的

Start-Process参数指示它将生成的控制台子进程连接到其父级的标准流。

因此,在PowerShell作业中使用Start-Process -NoNewWindow,您将生成的cmd.exe进程连接到相同的流,PowerShell作业进程使用这些流与其自己的父进程交换消息。

现在,当生成cmd.exe将某些内容写入其标准输出流时,会干扰PowerShell作业进程与其父进程之间的正常消息交换,从而导致一些意外行为。

答案 1 :(得分:1)

PetSerAl很好地解释了为什么会发生这种情况,但是花了我一些时间才找到合适的解决方案。

第一件事-正如某些人提到的不使用-NoNewWindow,而是使用-WindowStyle Hidden

第二,将结果输出到文件并在脚本块中处理它们。有两个参数,一个用于输出,另一个用于错误-RedirectStandardOutput-RedirectStandardError。 由于某些原因,我确定第一个将处理所有输出,并且如果没有错误,我的代码可以正常工作,但是如果脚本块中出现异常,则我的代码将失败并且没有输出。

我创建了一个还可以处理过程状态结果的函数:

function RunProcesSafe($pathToExe, $ArgumentList)
{               
 Write-Host "starting $pathToExe $ArgumentList"
 $logFile = Join-Path $env:TEMP ([guid]::NewGuid())
 $errorLogFile = Join-Path $env:TEMP ([guid]::NewGuid())
 try
 {
    Write-Host "starting $pathToExe $ArgumentList"
    $proc = Start-Process "$pathToExe" -Wait -PassThru -RedirectStandardError $errorLogFile -RedirectStandardOutput $logFile -WindowStyle Hidden -ArgumentList $ArgumentList
    $handle = $proc.Handle          
    $proc.WaitForExit();
    if ($proc.ExitCode -ne 0) {
         Write-Host "FAILED with code:"+$proc.ExitCode
         Throw "$_ exited with status code $($proc.ExitCode)"
    }
 }
 Finally
 {
    Write-Host  (Get-Content -Path $logFile) 
    Write-Host  (Get-Content -Path $errorLogFile) 
    Remove-Item -Path $logFile -Force
    Remove-Item -Path $errorLogFile -Force
 }         
}