Propagating errorlevel ?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Propagating errorlevel ?

#1 Post by Ed Dyreen » 17 Jan 2012 20:14

'
From the command shell, taskkill returns errorlevel 128

Code: Select all

prompt $_$G
>for /f "usebackq delims=" %? in (`taskKill.EXE /t /f /im "%%~a" 2^>^&1`) do echo.?=%?_
>echo.?=Fout: het proces %~a is niet gevonden._
?=Fout: het proces %~a is niet gevonden._
>echo.%errorlevel%
128
>
Not from batch though

Code: Select all

for /f "usebackq delims=" %%? in (`taskKill.EXE /t /f /im "%%~a" 2^>^&1`) do echo.?=%%?_
echo.%errorlevel%
pause

Code: Select all

?=Fout: het proces ~a is niet gevonden._
0
Druk op een toets om door te gaan. . .
Hmmm, that's obviously wrong, the errorlevel should be 128 :?

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Propagating errorlevel ?

#2 Post by Ed Dyreen » 17 Jan 2012 20:58

'
I've been trying yet I see no other solution than this highly inefficient one:

Code: Select all

taskKill.EXE /t /f /im "%%~a">nul 2>&1||(
   set/a$errcod=!errorlevel!
   for /f "usebackq delims=" %%? in (`taskKill.EXE /t /f /im "%%~a"2^>^&1`) do (
      set "$errmsg=%%?"
   )
)
Well, at least it works, that is it captures both the errorlevel and the errormessage :|

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Propagating errorlevel ?

#3 Post by dbenham » 17 Jan 2012 22:17

You fooled yourself from the command line - neither context returns the errorlevel :!: :wink:

The ERRORLEVEL 128 you saw from the command line was probably a residual value from a previous command.

Remember that the FOR IN() clause is executed in its own CMD shell, and the ERRORLEVEL is not propagated to the parent shell. Even if you explicitly exit with an error code, the ERRORLEVEL is not propagated.

You could do something like this to capture the ERRORLEVEL

Code: Select all

@echo off
setlocal enableDelayedExpansion
for /f "usebackq delims=" %%? in (`cmd /v:on /c "2>&1 taskKill.EXE /t /f /im "%%~a" & echo error=^!errorlevel^!"`) do (
  echo %%? | findstr /v /b /c:"error=" || set %%?
)
echo The command "returned" errorlevel=%error%

Even though the parent has delayed expansion enabled, you still have to use CMD /V:ON because CMD does not inherit the delayed expansion state. Note the ! must be escaped in the IN() clause, otherwise !errorlevel! will be expanded in the parent batch context.

Dave Benham

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Propagating errorlevel ?

#4 Post by Aacini » 17 Jan 2012 22:24

Do you think is very inefficient to use an auxiliary disk file?

Code: Select all

taskKill.EXE /t /f /im "%%~a" >nul 2>message.txt
set $errcod=%errorlevel%
set /P $errmsg=< message.txt

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Propagating errorlevel ?

#5 Post by dbenham » 17 Jan 2012 23:04

I thought about using a temp file, and came to the conclusion that it might actually be more efficient as well as simpler to code. Don't ask me why I didn't try implementing it :lol:

Code: Select all

@echo off
setlocal enableDelayedExpansion
for /f "usebackq delims=" %%? in (`cmd /v:on /c "2>&1 taskKill.EXE /t /f /im "%%~a" & echo ^!errorlevel^!>errcode.txt"`) do echo %%?
<errcode.txt set /p "error="
del errcode.txt
echo The command "returned" errorlevel=%error%

The temp file version is about 15% faster on my machine


Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Propagating errorlevel ?

#6 Post by Ed Dyreen » 18 Jan 2012 00:00

dbenham wrote:You fooled yourself from the command line - neither context returns the errorlevel :!: :wink:
No I didn't:

Code: Select all

prompt $_$G &cls
and

Code: Select all

>echo.%errorlevel%
0
>taskKill.EXE /t /f /im "%%~a"
Fout: het proces %~a is niet gevonden.
>echo.%errorlevel%
128
>
:shock: Maybe is different on Vista
...Unfortunately the return value from taskkill is 0 in both cases we're having here: criteria met or not met (the return value is 128 if the image name is invalid, though)....
http://stackoverflow.com/questions/854708/taskkill-in-an-if-condition

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Propagating errorlevel ?

#7 Post by dbenham » 18 Jan 2012 07:01

Ed Dyreen wrote:
dbenham wrote:You fooled yourself from the command line - neither context returns the errorlevel :!: :wink:
No I didn't:

Code: Select all

prompt $_$G &cls
and[code]
>echo.%errorlevel%
0
>taskKill.EXE /t /f /im "%%~a"
Fout: het proces %~a is niet gevonden.
>echo.%errorlevel%
128

Try running the taskKill from within a FOR IN() clause on the command line, like your original post, and see what happens. (Again, make sure errorlevel is 0 before testing) :wink:


Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Propagating errorlevel ?

#8 Post by Ed Dyreen » 18 Jan 2012 07:34

'
Why you want me to test it with a for ? Can you be a little more clear ?
You describe exactly the problem, from within a for, I predict the errorlevel will be 0.
I tested that yesterday.

The code I use always generate error 128 if /IM is invalid:

Code: Select all

taskKill.EXE /t /f /im "%%~a"^>nul 2^>^&1^|^|!tErr_!^^^!errorlevel^^^!+1000%$n1c%
How is your example any different :?:

Code: Select all

@echo off
setlocal enableDelayedExpansion
for /f "usebackq delims=" %%? in (`cmd /v:on /c "2>&1 taskKill.EXE /t /f /im "%%~a" & echo error=^!errorlevel^!"`) do (
  echo %%? | findstr /v /b /c:"error=" || set %%?
)
echo The command "returned" errorlevel=%error%
pause
exit

Code: Select all

Fout: het proces ~a is niet gevonden.
The command "returned" errorlevel=128
Druk op een toets om door te gaan. . .
I have the impression you are teasing me, already this topic is longer than it should be :)

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Propagating errorlevel ?

#9 Post by dbenham » 18 Jan 2012 12:04

Sorry Ed - there must have been a miscommunication somewhere.

From your original post, you appeared to claim that the errorlevel was propagated outside of the FOR IN() clause back to the parent if executed from the command line.
Ed Dyreen wrote:'
From the command shell, taskkill returns errorlevel 128
[code]
prompt $_$G
>for /f "usebackq delims=" %? in (`taskKill.EXE /t /f /im "%%~a" 2^>^&1`) do echo.?=%?_
>echo.?=Fout: het proces %~a is niet gevonden._
?=Fout: het proces %~a is niet gevonden._
>echo.%errorlevel%
128
>

That is what I was referring to when I said you must have fooled yourself. The error 128 above could not have come from the FOR IN(taskKill). It must have come from a prior command.

Then in your next to last post you provided an example showing taskKill returning error 128 when not executed within FOR IN(). Of course that will work, but it doesn't address the point I was making. So I thought you were still confused.

Now based on your last post it sounds like you understand the point I was making.

I really wasn't trying to mislead or tease you. Based on my interpretation of your posts, I thought you were confused about the significance of executing a command within a FOR IN() with regard to errorlevel.

Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Propagating errorlevel ?

#10 Post by Ed Dyreen » 18 Jan 2012 12:38

'
I see, thanx for in (refreshing my memory) :mrgreen:

Dragokas
Posts: 43
Joined: 30 Jul 2013 09:42
Location: Ukraine, USSR
Contact:

Re: Propagating errorlevel ?

#11 Post by Dragokas » 30 Jul 2013 15:30

Hello Ed Dyreen.
It's interesting tip to set variable from filtered string )))
But anyway, errorlevel is a last string = last iteration. So, more easy:

Code: Select all

@echo off
setlocal enableDelayedExpansion
for /f "delims=" %%? in ('cmd /v:on /c "2>&1 taskKill /t /f /im "%%~a" & echo ^!errorlevel^!"') do (
  set error=%%?
)
echo The command "returned" errorlevel=%error%
pause


Best regards, Alex.
Last edited by Dragokas on 30 Jul 2013 17:26, edited 1 time in total.

Dragokas
Posts: 43
Joined: 30 Jul 2013 09:42
Location: Ukraine, USSR
Contact:

Re: Propagating errorlevel ?

#12 Post by Dragokas » 30 Jul 2013 15:36

For both, error message and error code I recommend to use the trick, when you set value of 2-nd variable to the 1-st variable before 2-nd is defined. So, you can read previous line in the cycle:

Code: Select all

@echo off
setlocal enableDelayedExpansion
for /f "delims=" %%? in ('cmd /v:on /c "2>&1 taskKill /t /f /im "%%~a" & echo ^!errorlevel^!"') do (
  set errmsg=!error!
  set error=%%?
)
echo The command "returned" errorlevel=%error%
echo Message is: %errmsg%
pause

Post Reply