使用Powershell和Try-Catch以及外部EXE进行输出重定向/捕获问题

时间:2021-02-06 00:38:45

First off, either A) I'm not investigating into this hard enough or B) I've found a problem that requires some funky hack. By the way this is posh v1.0.

首先,要么A)我不是在考虑这个问题,或者B)我发现了一个需要一些时髦黑客的问题。顺便说一下,这是豪华版v1.0。

Here it goes:

它来了:

A week or so ago I asked a question about redirecting the output from the exection of an EXE in powershell that was otherwise not being caught. I was swiftly presented with "2>&1" which solved the problem.

大约一个星期前,我问了一个问题,关于在PowerShell中执行EXE的输出重定向,否则它将被捕获。我很快得到了“2>&1”,这解决了这个问题。

Now I've hit another snag and hope to see what some of you *ers can throw at it.

现在我又遇到了另一个障碍,并希望看到你们中的一些人可以扔掉它们。

I'm using try-catch blocks throughout my code as a good programmer should. When I went to place a call to GPG (gnupg.org), passing it a few commands as follows:

我在代码中使用try-catch块作为优秀的程序员应该。当我打电话给GPG(gnupg.org)时,传递一些命令,如下所示:

try `
{
    & $gpgExeLocation --import $keyFileName 2>&1 | out-file "theOutput.txt";
} `
-Catch `
{
    write-host "$_";
}

I get a blank text file (theOutput.txt).

我得到一个空白文本文件(theOutput.txt)。

But if I do the same call outside of the try-catch block, the text file gets some text written to it as expected.

但是如果我在try-catch块之外执行相同的调用,则文本文件会按预期写入一些文本。

What I'm wondering is if there is an issue with output redirection to stdout and the way powershell traps exceptions - or if it is my try-catch code to begin with?

我想知道是否存在输出重定向到stdout的问题以及powershell捕获异常的方式 - 或者如果它是我的try-catch代码开始?

here is my try-catch implementation

这是我的try-catch实现

function global:try
{
    param
    (
        [ScriptBlock]$Command = $(Throw "The parameter -Command is required."),
        [ScriptBlock]$Catch   = { Throw $_ },
        [ScriptBlock]$Finally = {}
    )

    & {
        $local:ErrorActionPreference = "SilentlyContinue"

        trap
        {
            trap
            {
                & {
                    trap { Throw $_ }
                    &$Finally
                }

                Throw $_
            }

            $_ | & { &$Catch }
        }

        &$Command
    }

    & {
        trap { Throw $_ }
        &$Finally
    }
};

1 个解决方案

#1


It appears you are using a custom Try function with a -Catch parameter. Mind sharing your implementation to see if that could be causing the problem?

您似乎正在使用具有-Catch参数的自定义Try函数。介意分享您的实施,看看是否可能导致问题?

BTW I doubt that your catch statement would ever be invoked unless you are converting the non-terminating error condition of $lastexitode -ne 0 to a terminating error. In this case, you may be better off with a function like this. I use it a lot (it's quite handy):

顺便说一下,我怀疑你的catch语句是否会被调用,除非你将$ lastexitode -ne 0的非终止错误条件转换为终止错误。在这种情况下,使用这样的函数可能会更好。我经常使用它(它非常方便):

function Get-CallStack {
    trap { continue }
    1..100 | foreach {
        $var = Get-Variable -scope $_ MyInvocation
        $var.Value.PositionMessage -replace "`n"
    }
}

#--------------------------------------------------------------------
# Helper function to deal with legacy exe exit codes
#--------------------------------------------------------------------
function CheckLastExitCode {
    param ([int[]]$SuccessCodes = @(0), [scriptblock]$CleanupScript=$null)

    if ($SuccessCodes -notcontains $LastExitCode) {
        if ($CleanupScript) {
            "Executing cleanup script: $CleanupScript"
            &$CleanupScript
        }
        $OFS = $NL = [System.Environment]::NewLine
        throw "EXE RETURNED EXIT CODE ${LastExitCode}${NL}$(Get-CallStack)"
    }
}

Use it like so:

像这样使用它:

& $gpgExeLocation --import $keyFileName 2>&1 | out-file "theOutput.txt"
CheckLastExitCode

#1


It appears you are using a custom Try function with a -Catch parameter. Mind sharing your implementation to see if that could be causing the problem?

您似乎正在使用具有-Catch参数的自定义Try函数。介意分享您的实施,看看是否可能导致问题?

BTW I doubt that your catch statement would ever be invoked unless you are converting the non-terminating error condition of $lastexitode -ne 0 to a terminating error. In this case, you may be better off with a function like this. I use it a lot (it's quite handy):

顺便说一下,我怀疑你的catch语句是否会被调用,除非你将$ lastexitode -ne 0的非终止错误条件转换为终止错误。在这种情况下,使用这样的函数可能会更好。我经常使用它(它非常方便):

function Get-CallStack {
    trap { continue }
    1..100 | foreach {
        $var = Get-Variable -scope $_ MyInvocation
        $var.Value.PositionMessage -replace "`n"
    }
}

#--------------------------------------------------------------------
# Helper function to deal with legacy exe exit codes
#--------------------------------------------------------------------
function CheckLastExitCode {
    param ([int[]]$SuccessCodes = @(0), [scriptblock]$CleanupScript=$null)

    if ($SuccessCodes -notcontains $LastExitCode) {
        if ($CleanupScript) {
            "Executing cleanup script: $CleanupScript"
            &$CleanupScript
        }
        $OFS = $NL = [System.Environment]::NewLine
        throw "EXE RETURNED EXIT CODE ${LastExitCode}${NL}$(Get-CallStack)"
    }
}

Use it like so:

像这样使用它:

& $gpgExeLocation --import $keyFileName 2>&1 | out-file "theOutput.txt"
CheckLastExitCode