Powershell return code


  • I survived the hour long Uno hand

    Search is awful so rather than find my old Powershell thread I'm starting new one for this quick question.

    I am running commands, like:

    #Use 7zip
    set-alias sz "$env:ProgramFiles\7-Zip\7z.exe"
    
    #Unzip
    Write-Host "Unzipping new files"
    sz e "temp.tar.gz"
    sz x "temp.tar" -aoa
    

    How do I get the return code of the sz execution so I can test it and return failure if it failed?



  • The following cmd idiom is of course far too succinct to work properly in powershell:

    sz x "temp.tar" -aoa || echo 7-Zip extraction failed
    

  • I survived the hour long Uno hand

    @flabdablet That doesn't do what I want. I want to test the return code and return from the script if execution fails, though I may need to execute some cleanup steps before I go.

    My current version isn't working:

    If (-Not (Test-Path "C:\webfiles\${appName}")) {
        Write-Host "Build did not unpack, aborting."
        Return -2;
    }
    

    That does exactly what it seems to do, except for the fact that if I didn't have permission to delete the old build, it returns a success for the deploy, because code is still on the machine.



  • @Yamikuronue According to the page I linked, you'd want something like

    #Use 7zip
    set-alias sz "$env:ProgramFiles\7-Zip\7z.exe"
    
    #Unzip
    Write-Host "Unzipping new files"
    sz e "temp.tar.gz"
    if ($?) {
        sz x "temp.tar" -aoa
        if ($?) {
            echo "All good"
        } else {
            echo "sz x failed, exit code $LASTEXITCODE"
        }
    } else {
        echo "sz e failed, exit code $LASTEXITCODE"
    }
    

  • I survived the hour long Uno hand

    @flabdablet said:

    ($?)

    That's what I needed, thanks.



  • Adapting the test from your current version:

    If (!$?) {
        Write-Host "Build did not unpack, error $LASTEXITCODE; aborting."
        Return -2;
    }
    

    Note that $? is highly volatile and reflects the error result of the previous powershell statement regardless of type. $LASTEXITCODE is affected only by running .exes.



  • $LastExitCode automatic variable has the exit code of the last Windows-based program (i.e., not a cmdlet). The $? automatic variable contains the last statement's execution status, true for success and false for failure. The $Error automatic variable contains recent errors. $Error[0] is the most recent error. See Get-Help about_Automatic_Variables -ShowWindow.

    My last script that archived used:

    $7Zip = 'C:\Program Files\7-Zip\7z.exe';
    
    [...]
    
    &"$7Zip" a "$ArchiveFile" "$FullLogPath\$LogFileSpec" -mx=9 -mmt=on
    If ($LastExitCode -Eq 0) {
        Remove-Item "$FullLogPath\$LogFileSpec"
    }
    Else {
        Throw "Error executing 7Zip: $7Zip a $ArchiveFile $FullLogPath\$LogFileSpec -mx=9 -mmt=on"
    }


  • @Yamikuronue said:

    @flabdablet said:

    ($?)

    That's what I needed, thanks.

    $? exists in Posix shells like bash as well, except that it contains the previous command's exit code rather than a boolean.

    When in doubt, treat powershell like bash with all the conveniences stripped out. In this case the missing convenience is the ability to treat any sequence of commands as a boolean conditional, where the condition is true if the last command in the sequence exited with no error. Powershell is all modern and strongly typed and shit, so it looks down its nose at behavior like that.


  • I survived the hour long Uno hand

    @flabdablet said:

    When in doubt, treat powershell like bash with all the conveniences stripped out.

    I never assume Powershell uses the same syntax as bash. I assume it has the same capabilities, but I never am quite sure on the syntax.

    My linux deploy script uses

    retval=$?;
    [...]
    return $retval
    

    so I figured it was possible, but I didn't know it was the exact same syntax. Now I do.



  • @Yamikuronue If you're going to return the actual code from the last command that went wrong, you probably want to return $LASTEXITCODE instead of -2. But this is Windows, so that's probably not what you want, because there are no conventions at all for the meanings of exit codes on Windows; defining your own failure codes will probably work better in the long run.


  • FoxDev

    @flabdablet said:

    because there are no conventions at all for the meanings of exit codes on Windows

    That's not strictly true; there is a convention where a positive return code is success, and negative is failure. Not sure if that applies to Powershell though; it might just be a Win32 API thing.


  • I survived the hour long Uno hand

    @flabdablet said:

    If you're going to return the actual code

    I'm not, I'm returning codes based on which step in the deploy process failed. The unpack is step 2, so it returns -2 if it failed. I figure that's as good a convention as any.


  • Discourse touched me in a no-no place

    @RaceProUK said:

    @flabdablet said:

    because there are no conventions at all for the meanings of exit codes on Windows

    That's not strictly true; there is a convention where a positive return code is success, and negative is failure. Not sure if that applies to Powershell though; it might just be a Win32 API thing.

    Actually, it is. The errorlevel is a positive integer in the range 0..255.

    ETA: Unless powershell does something different from cmd.exe with exit codes. WIn32 API functioons, what you said is generally correct, as long as we're not talking about HRESULTS.


Log in to reply