12

I am trying to launch a PowerShell command through Windows command prompt to replace a text into a file. The problem is that I am always getting ErrorLevel = 0 even when my PowerShell command is not working. My question is how to get an error code into ErrorLevel when I launch PowerShell through cmd? Please note that I would like to make this through the Windows command prompt and not by creating a script a part.

Here is an example of what I am saying. The error in the print screen is made intentionally by choosing an non existing file to show you that even when there is an error, the ErrorLevel is equal to 0.

The command I am using is the following (I tried $LastExitCode and $ExitCode):

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $LastExitCode"

But I also tried the same with:

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $ExitCode"

Based on the comment of majkinetor, I tried the following and hasn't work as well :(, I am keep getting ErrorLevel 0 in Dos even when an error occurs in powershell.

powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {exit $LastExitCode}"

You can see clearly an error related to the file name that it doesn't exist, but the error level is always 0.

What I want is to get an error code other than the 0 for each error that happens while executing the PowerShell command.

Error 2

11
  • 2
    @Bill_Stewart, when we ask for a help, it's not to get an answer about something else...your comment wasn't helpfull at all..if I wanted to make it with a different way I wouldn't ask my question Commented May 1, 2016 at 12:49
  • 1
    @KenWhite Personnaly when I read a question and want to help, I prefere print screens more than codes only...anyway I will crop the images, but I won't delete them...thanks anyway Commented May 1, 2016 at 12:50
  • 1
    Great. You stand alone. I gave you a long list of the many reasons this site does not prefer images, and apparently you didn't read it. The biggest reason to avoid code in images is that people can't copy and paste it to use to try to help, and most are not willing to retype it all. So if you want to reduce (or at least delay) your chances of getting help, keep posting code in images. Commented May 1, 2016 at 15:02
  • 1
    @Bill_Stewart You can't judge when you don't know the environnement of the company and asker etc...if you have an answer to a question give it, and if you don't have it's ok, no need to ask the person to do something else...if i wanted or could do it with a different way I wouldn't ask my question here .... Thanks for respecting people's question. I know why I am asking to do it that way, and am not into writing 5 pages to explain the why, i tried to go directly to the target and ask a direct question.. Commented May 2, 2016 at 8:27
  • 1
    You are getting zero because that is the value you are passing. If you want to use either one of your variables as the exit code you have to set them to something. Commented May 2, 2016 at 9:05

7 Answers 7

9

Try this code in cmd.exe shell :

C:> powershell -noprofile -command " try { 1/0 } catch {exit 22}"

C:> echo %errorlevel%
22

So, add your commands in try block. If it happens that you call non powershell command you could exit $LastExitCode (but from within try block).


EDIT

OK, I know what is going on with your non-working code, it never passed trough catch block as Get-Content produces non-terminating error. You have to take care about that:

C:> Powershell -Command "try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref -ea stop } catch {$_; exit 123 }"

Get-Content : Cannot find path 'C:\Users\majkinetor\HvsvmAppserver.ref' because it does not exist.
At line:1 char:8
+ try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0. ...
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\majkinetor\HvsvmAppserver.ref:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

C:> echo %errorlevel%
123

Notice the -ea stop that I added to both commands (shorter then ErrorAction). My solution was correct the first time, however, you need to understand that script must be designed correctly too. You might also want to use trap instead catch, but you still have to use EA stop. Perhaps the shortest general solution that doesn't depend too much on a script is:

   $ErrorActionPreferance = 'Stop'
   <your script goes here, no need for -ea stop in it>
   trap { exit 123 }

This will not work if the script in question changes $ErrorActionPreference (which rarely happens) but will work in all other cases.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks a lot, I will try that tomorrow at work and will let you know if it solved or not my problem.
Dunno if I got it well, but I tried and keep getting the Error Level 0 ... here is the command that I used . powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {exit $LastExitCode}"
I even tried this (even if i don't want a cuztom error) and i keep getting errorlevel 0 .... Dunno the ones who voted +2 to your answer if they tested it or just voted without even testing... powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {exit 12345}"
You didn't do it right. Do not return with exit $LastExitCode, it is always 0 in your case. Since you used posh cmdlet it doesn't return errorlevel at all but error object $_. Use exit 1 for example.
as you see in the code just above your comment I am not using $LastExitCode, I put exit 12345 and i still get 0 !
|
1

Consider using the option -file instead of -command. By using -file option, you will get any value, you have specified in your code, while the -command option will provide you either 0, or 1.

Try this scenario:

> cmd.exe

> cd %userprofile%\desktop
> echo $temp=999;write-host $temp;exit $temp > test.ps1
> echo %errorlevel%
0

> powershell .\test.ps1
999

> echo %errorlevel%
1

> powershell -command .\test.ps1
999

> echo %errorlevel%
1

And now ...

> powershell -file .\test.ps1
999

> echo %errorlevel%
999

Good luck!

Comments

0

So to put this as an answer based on my comment:

You are getting zero because that is the value you are passing. If you want to use either one of your variables as the exit code you have to set them to something.

To which you responded:

@ShawnMelton Thanks, but I haven't get it well....I don't want to make my own error code or personnalized error management ! All I want is that when an error occured in my powershell (code, scripts etc...), the error level of Dos get this error code (I don't want to make my own code). Can you illustrate by a code what do you mean ? I may have not understand your comment ? thanks for trying to help it's nice from your side.

Being that you are calling powershell.exe it is going to return an exit code back to the command prompt, always as zero (0). It will always be zero even if you execute PowerShell code that is incorrect. The powershell.exe itself is successfully executing any command you pass to it so unless the executable itself errors for some reason, you always get zero. If you want PowerShell.exe to return something other than zero you are required to use the exit xx in your PowerShell command, where xx is an integer. enter image description here

Which the point made of not trying to call PowerShell from a command prompt still stands, whether you want to here it or not. You are not guaranteed that even using something like exit 99 is going to always overwrite the executable returning zero...it is just the way it works. I got various results when I tried it on my laptop with Windows 10. I can say that I have used technique before in production when I have had to call PowerShell scripts from SSIS packages, and it served the purpose. However in that situation I was not calling it from a batch file so it worked as expected.

5 Comments

@Shwan Melton, thanks a lot. Now I understand why I have always 0. Still the second part that I don't understand, is why if I put exit 99, I won't get it 99 ? would you please clarify me again the second part of your answer ? As for why I ma doing that through dos, it's because at my company they have very long .cmd, and If I want to modify anything I am obliged to use this .cmd and can't write external scripting etc...Othwerwise I could have done what I want using a .vbs, but the rules we have are complicated and I can't do all I want, am obliged to do it in the unique .cmd
Executing PowerShell scripts via command prompt (DOS) does not guarantee that you can change the exit code to be anything other than zero.
So to conclude I can't do what I want, or to make it clear, I can do it, but I can't guarantee to manage potential errors...did I get it well this time ? :)
I am sure this is wrong - Continuous build depends on powershell returning something other then 0 when things fail in order to stop the build. I have used this approach number of times and it works. The example I have given was tested on Win7,8,10 with Powershell 4,5.
Actually exit is documented as setting ErrorLevel: learn.microsoft.com/en-us/powershell/module/…
0

The suggestion by @majkinetor definitely works. I mean this one:

powershell -Command "try {(gc "C:\test.txt" -ea stop) -creplace 'test', 'work' | Out-File -encoding ASCII "C:\test.txt" -ea stop} catch{ exit 1}"

If the file path is correct, the string is replaced. If the file path is incorrect - the error level in the cmd session is set to 1 with the above snippet.

The issue I encountered, is in the case that I want this to fail a Jenkins build. I use build step Execute Windows batch command and the trick is that you need to have only the above command if you want it to fail the build upon error. If you have another one afterwards and it is successful - the build is successful.

Comments

0

If you use an external command last, it will set the errorlevel. I'm quoting the pipe with a "^".

powershell echo hi ^| findstr hi2

Or you can test $? and exit with a nonzero number:

powershell 1/0; if (! $?) { exit 1 } 

Actually if the LAST cmdlet raises an error, terminating or not, it should set the cmd errorlevel.

You can do something like this, and exit with the number of errors made.

powershell $errorcount = $error.count; 1/0; echo hi; exit $error.count - $errorcount

Script terminating errors will set the errorlevel:

powershell throw 'hi'

Thinking more about the original problem. If you don't use the parentheses, the errorlevel will get set if it can't find the file, since the current pipeline will have an exception. But the output file would have to be different. Running it as a script wouldn't give the same result (neither would unix).

powershell "get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3"

get-content : Cannot find path 'C:\Users\admin\foo2' because it does not exist.
At line:1 char:1
+ get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\admin\foo2:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand


echo %errorlevel%

1

Comments

0

The easiest way is to use "trap {break};" in the powershell code. If an error occurs, execution is aborted, which returns %errorlevel% = 1. It looks like this:

powershell.exe "trap {break}; {Your powershell code}"
echo %errorlevel%

You can also use && and || to execute commands on success and failure. For example:

powershell.exe "trap {break}; {Your powershell code}" && (echo All is good) || (echo There is a problem)

If you want to assign a specific %errorlevel% to specific errors in powershell, you will have to use the "try {} catch {}" construct. For example:

powershell.exe "try {Get-Content -Path 'C:\Files\*' -ErrorAction Stop} catch [System.UnauthorizedAccessException] {exit 17}"
if "%errorlevel%" == "17" (echo File is not accessible)

In a generally way, it looks like this:

powershell.exe "try {Your powershell code} catch [Exception1] {exit 1} catch [Exception2] {exit 2} catch [Exception3] {exit 3}"
if "%errorlevel%" == "1" (echo Problem description 1)
if "%errorlevel%" == "2" (echo Problem description 2)
if "%errorlevel%" == "3" (echo Problem description 3)

Comments

0

This is kind of a malformed question, since there is no $exitcode and $lastexitcode is only set for external non-powershell commands. At least if the last line in powershell has an exception, powershell -command (not -file) will return errorlevel 1 in cmd. $? or $false would only do the opposite of what you want.

powershell -command get-childitem foo4

get-childitem : Cannot find path 'C:\Users\js2010\foo4' because it does not exist.
At line:1 char:1
+ get-childitem foo4
+ ~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\js2010\foo4:String) [Get-Child
   Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand


echo %errorlevel%

1

With -file, you can exit $error.count to count all the exceptions:

'get-childitem foo4
exit $error.count' | set-content file.ps1

powershell -file file.ps1

get-childitem : Cannot find path 'C:\Users\js2010\foo4' because it does not exist.
At C:\Users\js2010\foo\file.ps1:1 char:1
+ get-childitem foo4
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\js2010\foo4:String) [Get-Child
   Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand


echo %errorlevel%

1

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.