none
Obtaining errorlevel return codes in Powershell - Is it possible?

    Question

  • I have see quite a few ways of starting a program, such as 7-zip, from within Powershell.  However, I have not found a way of capturing the return codes from this program.  These are accessible at the command line level in the %errorlevel% variable. 

    How do I gain access to the equivalent of %errorlevel% in Powershell.  Is it possible?


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 1:53 PM

Answers

  • sure you can.

    $LASTEXITCODE is the equivalent to %ERRORLEVEL%


    If you found this post helpful, please "Vote as Helpful". If it answered your question, remember to "Mark as Answer"
    MCC & PowerShell enthusiast
    http://oliver.lipkau.net/blog
    Tuesday, October 11, 2011 2:11 PM
    Moderator
  • I have see quite a few ways of starting a program, such as 7-zip, from within Powershell.  However, I have not found a way of capturing the return codes from this program.  These are accessible at the command line level in the %errorlevel% variable. 

    How do I gain access to the equivalent of %errorlevel% in Powershell.  Is it possible?


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"


    $LASTEXITCODE

     


    jv
    Tuesday, October 11, 2011 2:10 PM
  • PS C:\scripts> & "C:\Program Files\7-Zip\7z.exe a h:\test c:\scripts"

    In this case, you're telling PowerShell that the entire quoted string is the name of the executable.

    Close the quote after the executable's file name and put the parameters after it:

    & "C:\Program Files\7-Zip\7z.exe" a H:\test C:\scripts

    Bill

    • Marked as answer by Bigteddy Tuesday, October 11, 2011 2:58 PM
    Tuesday, October 11, 2011 2:53 PM
    Moderator
  • For example, in this code, the command is bogus, and returns an %errorlevel% of 7, but $lastexitcode remains 0:

     [System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $lastexitcode

     

    With a diagnostic launch or with wmi create or an other form of process creation the ExitXode is on the process object.

    $proc=[System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $proc.ExitCode
    
    
    

     


    jv
    • Proposed as answer by jrv Tuesday, October 11, 2011 3:06 PM
    • Marked as answer by Bigteddy Tuesday, October 11, 2011 3:12 PM
    Tuesday, October 11, 2011 3:01 PM
  • Hi jv,

    Yes, that's correct. If you want to run an executable from PowerShell and the path and/or filename of the executable contains spaces, you must enclose the executable's name in quotes and call it using the invocation operator (&).

    Bill

    • Marked as answer by Bigteddy Tuesday, October 11, 2011 4:19 PM
    Tuesday, October 11, 2011 3:52 PM
    Moderator

All replies

  • I have see quite a few ways of starting a program, such as 7-zip, from within Powershell.  However, I have not found a way of capturing the return codes from this program.  These are accessible at the command line level in the %errorlevel% variable. 

    How do I gain access to the equivalent of %errorlevel% in Powershell.  Is it possible?


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"


    $LASTEXITCODE

     


    jv
    Tuesday, October 11, 2011 2:10 PM
  • sure you can.

    $LASTEXITCODE is the equivalent to %ERRORLEVEL%


    If you found this post helpful, please "Vote as Helpful". If it answered your question, remember to "Mark as Answer"
    MCC & PowerShell enthusiast
    http://oliver.lipkau.net/blog
    Tuesday, October 11, 2011 2:11 PM
    Moderator
  • Well, I've tried $lastexitcode, and it always returns 0, whatever the executable does.

    For example, in this code, the command is bogus, and returns an %errorlevel% of 7, but $lastexitcode remains 0:

    [System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $lastexitcode
    


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 2:35 PM
  • Hi Bigteddy,

    Why use [System.Diagnostic.Process]::Start? Just run the executable:

    & "C:\Program Files\7-zip\7z.exe" ...

    Bill

    Tuesday, October 11, 2011 2:41 PM
    Moderator
  • Hi Bill, see below:

    PS C:\scripts> & "C:\Program Files\7-Zip\7z.exe a h:\test c:\scripts"
    $lastexitcode
    The term 'C:\Program Files\7-Zip\7z.exe a h:\test c:\scripts' is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:3
    + & "C:\Program Files\7-Zip\7z.exe a h:\test c:\scripts"
    +   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\Program File...test c:\scripts:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
     
    0

    I have to pass 7z parameters, and my way seems to be about the only way to do it.  You can't pass parameters with Invoke-Item.

    So your solutions are not, in my case, answers (yet).  If I remove the parmeters, it works fine, but just displays a help list of how to use it.  One must pass parameters to this command, and we really need that errorlevel.


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 2:51 PM
  • Well, I've tried $lastexitcode, and it always returns 0, whatever the executable does.

    For example, in this code, the command is bogus, and returns an %errorlevel% of 7, but $lastexitcode remains 0:

     

    [System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $lastexitcode
    

     


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"


    The problem is that the lastexitcode is set by teh shell. If you launch without a shell it won't get set.

    Try this to a non-existant  location

    PS>cmd /c dir x:\
    The system cannot find the path specified.
    PS>$lastexitcode
    1

    cmd /c dir c:\
    ....listing of c root
    $lastexitcode
    0

    Use the following form but if that fails to get the exitcode use the second version.

    C:\Program Files\7-Zip\7z.exe aaa h:\test c:\scripts

    cmd /C C:\Program Files\7-Zip\7z.exe aaa h:\test c:\scripts

     

     


    jv

     

    • Edited by jrv Tuesday, October 11, 2011 2:56 PM
    Tuesday, October 11, 2011 2:51 PM
  • PS C:\scripts> & "C:\Program Files\7-Zip\7z.exe a h:\test c:\scripts"

    In this case, you're telling PowerShell that the entire quoted string is the name of the executable.

    Close the quote after the executable's file name and put the parameters after it:

    & "C:\Program Files\7-Zip\7z.exe" a H:\test C:\scripts

    Bill

    • Marked as answer by Bigteddy Tuesday, October 11, 2011 2:58 PM
    Tuesday, October 11, 2011 2:53 PM
    Moderator
  • Perfect!  Now I'll never have to use batch/cmd/dos again!
    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 2:59 PM
  • For example, in this code, the command is bogus, and returns an %errorlevel% of 7, but $lastexitcode remains 0:

     [System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $lastexitcode

     

    With a diagnostic launch or with wmi create or an other form of process creation the ExitXode is on the process object.

    $proc=[System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $proc.ExitCode
    
    
    

     


    jv
    • Proposed as answer by jrv Tuesday, October 11, 2011 3:06 PM
    • Marked as answer by Bigteddy Tuesday, October 11, 2011 3:12 PM
    Tuesday, October 11, 2011 3:01 PM
  •  

    With a diagnostic launch or with wmi create or an other form of process creation the ExitXode is on the process object.

    $proc=[System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $proc.ExitCode
    
    
    

     


    jv
    That didn't work, jv.  I just get a blank output when it should print 7.  Bill's method works, though.

    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 3:05 PM
  • Perfect!  Now I'll never have to use batch/cmd/dos again!
    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"


    You don't need to use the call operator.  That is mostly used when we have a command saved in a string. The beauty of PowerShell is that it will execute all programs at teh prompt in almost the same waas DOS.

    The time when we need to use quotes is when a path has spaces in it.  Your command does not have spaces.

    The following will work.

    C:\Program Files\7-Zip\7z.exe  aaa h:\test c:\scripts

    I believe 2zip gets added to the path so this would be even easier:

    7z  aaa h:\test c:\scripts

    In both cases $lastexitcode should get set.

     


    jv
    Tuesday, October 11, 2011 3:08 PM
  •  

    With a diagnostic launch or with wmi create or an other form of process creation the ExitXode is on the process object.

    $proc=[System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $proc.ExitCode
    
    
    

     


    jv
    That didn't work, jv.  I just get a blank output when it should print 7.  Bill's method works, though.

    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"


    I just ran it and it worked perfectly.  It sets the ExitCode property on the process object. It does not set $lastexitcode.

     

     


    jv
    Tuesday, October 11, 2011 3:11 PM
  • I just ran it and it worked perfectly.  It sets the ExitCode property on the process object. It does not set $lastexitcode.

     

     


    jv

    There is a serious bug with this PS 3.0 ISE editor.  After running this (and getting no output):

    $proc=[System.Diagnostics.Process]::Start( "C:\Program Files\7-Zip\7z.exe", 'aaa h:\test c:\scripts' )
    $proc.ExitCode
    


    ...I then go to the little command window at the bottom of the ISE, and type in:

    $proc.ExitCode <Enter>

    ...and magically it produces 7.  Run it again from the ISE, no output, do it again at the command line, output.  Definite bug with this CTP.  Starting to regret it.


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 3:16 PM
  •  just ran it and it worked perfectly.  It sets the ExitCode property on the process object. It does not set $lastexitcode

     

    That is one reason why I never use the ISE.  It behaves diffferently.  If I need to do really good debugging I use PrimaScript which has a really excellent PowerShell debugger.

    When we host PowerSHell in a form it has to run STA.  This can create issues like you are seeing.  I noticed this in PosH V1 when I built my first host and though a GUI would befun to work in.  Not!

     

     


    jv
    Tuesday, October 11, 2011 3:22 PM
  • The following will work.

    C:\Program Files\7-Zip\7z.exe  aaa h:\test c:\scripts

    It doesn't work for me:

    PS C:\> C:\Program Files\7-Zip\7z.exe -h
    The term 'C:\Program' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
    path was included, verify that the path is correct and try again.
    At line:1 char:11
    + C:\Program <<<<  Files\7-Zip\7z.exe -h
        + CategoryInfo          : ObjectNotFound: (C:\Program:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException

    This does work:

    PS C:\> & "C:\Program Files\7-Zip\7z.exe" -h
    
    7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
    
    Usage: 7z <command> [<switches>...] <archive_name> [<file_names>...]
           [<@listfiles...>]

    <Commands>
      a: Add files to archive
      b: Benchmark
      d: Delete files from archive
      e: Extract files from archive (without using directory names)
      l: List contents of archive
      t: Test integrity of archive
      u: Update files to archive
      x: eXtract files with full paths
    <Switches>
      -ai[r[-|0]]{@listfile|!wildcard}: Include archives
      -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives
      -bd: Disable percentage indicator
      -i[r[-|0]]{@listfile|!wildcard}: Include filenames
      -m{Parameters}: set compression Method
      -o{Directory}: set Output directory
      -p{Password}: set Password
      -r[-|0]: Recurse subdirectories
      -scs{UTF-8 | WIN | DOS}: set charset for list files
      -sfx[{name}]: Create SFX archive
      -si[{name}]: read data from stdin
      -slt: show technical information for l (List) command
      -so: write data to stdout
      -ssc[-]: set sensitive case mode
      -ssw: compress shared files
      -t{Type}: Set type of archive
      -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options
      -v{Size}[b|k|m|g]: Create volumes
      -w[{path}]: assign Work directory. Empty path means a temporary directory
      -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames
      -y: assume Yes on all queries

    Bill

    Tuesday, October 11, 2011 3:32 PM
    Moderator
  • Right Bill.

     

    I used this

    7z -h

    which works.  If we have to use teh quotes because of a space in teh path then we have to use the call operator which is what I though I had typed.

    Oops! I typed it wrong:

    The time when we need to use quotes is when a path has spaces in it.  Your command does not have spaces.

    The following will work.

    C:\Program Files\7-Zip\7z.exe  aaa h:\test c:\scripts

    I believe 2zip gets added to the path so this would be even easier:

    7z  aaa h:\test c:\scripts

    In both cases $lastexitcode should get set.

    It should have demoed what I wrote.

    The time when we need to use quotes is when a path has spaces in it.  Your command does not have spaces.

    The following will work.

    &'C:\Program Files\7-Zip\7z.exe'  aaa h:\test c:\scripts

    I though I had pasted the correct lines from teh Posh session but didn't.

    Note that I used single quotes.  I prefer this so the shell doesn't alter the line by accident.

    The issue in PoSH is that it will call CreateProcess with the first token as the program name.  We are not passing quotes to teh process we are just giving PosH a hint as to where the first token really is.

     

     


    jv
    Tuesday, October 11, 2011 3:47 PM
  • Hi jv,

    Yes, that's correct. If you want to run an executable from PowerShell and the path and/or filename of the executable contains spaces, you must enclose the executable's name in quotes and call it using the invocation operator (&).

    Bill

    • Marked as answer by Bigteddy Tuesday, October 11, 2011 4:19 PM
    Tuesday, October 11, 2011 3:52 PM
    Moderator
  • Hi jv,

    Yes, that's correct. If you want to run an executable from PowerShell and the path and/or filename of the executable contains spaces, you must enclose the executable's name in quotes and call it using the invocation operator (&).

    Bill


    Nicely put, Bill.  I'm much clearer on using the & operator now.  Thanks.
    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Tuesday, October 11, 2011 4:19 PM
  • I know this is old, but I wanted to add to it.  As already been mentioned, the answer is:

    $LASTEXITCODE

    A list of all of your variables is available as a PSDrive.  The way you can find this and other variables the might be useful is:

    [PS] C:\>cd variable:
    [PS] Variable:\>dir
    
    Name                           Value
    ----                           -----
    $                              variable:
    ?                              True
    ^                              cd
    _
    args                           {}
    ...etc...
    LASTEXITCODE                   0
    ...etc...

    You can get a list of all of your PSDrives with the Get-PSDrive command.  Hope this proves useful for self-discovery.

    • Proposed as answer by VertigoRay Wednesday, November 28, 2012 11:31 PM
    • Edited by VertigoRay Tuesday, September 10, 2013 11:30 PM formatting
    Wednesday, November 28, 2012 11:25 PM
  • Yes but why do it the hard way..

    gv

    That gets all variables.

    gv last*

    gv s*

    All of these get varaibles and with more info.

    What you have stumbled across is how we create variables and other things.

    variables are - dir variables:

    functions are dir functions:

    and

    dir env:
    dir alias:
    dir cert: -recurse

    ...more...

    Drives are created by providers.  Her is how we get the providers:

    help Get-PSProvider -full

    Get a good book onPowerSHell and all of this will be explained in a way that will help you understand what is there and how it is intended to be used.

    Oh!

    dir variable:lastexitcode

    or

    dir variable:?

    Now explain why that happens.  It will lead you to other really neat shortcuts.


    ¯\_(ツ)_/¯

    Wednesday, November 28, 2012 11:57 PM