views:

504

answers:

2

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.

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.

Now I've hit another snag and hope to see what some of you stackoverflowers 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 `
{
    & $gpgExeLocation --import $keyFileName 2>&1 | out-file "theOutput.txt";
} `
-Catch `
{
    write-host "$_";
}

I get a blank text file (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.

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?

Any help would be greatly appreciated.

+2  A: 

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?

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):

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
Keith Hill
I got trigger happy and didnt read your code. I'm going to try it out and see what happens. I appreciate it.
CLR
Success! Called gpg with some bad arguments and it caught the return code with ease. I appreciate the time you took to help. Cheers!
CLR
A: 

Since comments don't like lengthy posts I had to answer instead.

here is my try-catch implementation

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
    }
};
CLR