1 (изменено: wisgest, 2015-05-26 04:07:21)

Тема: CMD: Код возврата командного файла при запуске из внешнего приложения

Просматривая архив форума наткнулся в удалённой теме «VBS: получение кода ошибки?» на следующее:


2007-05-18 13:24:43

alexii пишет:

Хмм... Попутная тема. Для батника, запущенного из-под скрипта, у меня вообще получается интересная песня.

ReturnErrorlevel.cmd - сам батник, формирующий коды возврата:

@echo off
setlocal ENABLEEXTENSIONS

if /i "%~1%"=="SETFAILURE" (
    exit /b 1
) else (
    if /i "%~1%"=="SETOK" (
        exit /b 0
    ) else (
        exit /b 2
    )
)

endlocal

ReturnErrorlevel.vbs - аналогичный скрипт, формирующий коды возврата:

Dim objArgs
Dim intErrorlevel

Set objArgs = WScript.Arguments

If objArgs.Count <> 0 Then
    Select Case UCase(objArgs(0))
        Case "SETFAILURE"
             intErrorlevel = 1
        Case "SETOK"
             intErrorlevel = 0
        Case Else
             intErrorlevel = 2
    End Select
    
Else
    intErrorlevel = 2
End If

Set objArgs = Nothing

WScript.Quit intErrorlevel

Simple.cmd - батник для проверки кодов возврата:

@echo off
setlocal ENABLEEXTENSIONS

echo.
echo Calling ReturnErrorlevel.cmd
echo.

echo Calling with none parameter
    call ReturnErrorlevel.cmd
echo Errorlevel = %errorlevel%

echo Calling with SetOk parameter
call ReturnErrorlevel.cmd SetOk
echo Errorlevel = %errorlevel%

echo Calling with SetFailure parameter
call ReturnErrorlevel.cmd SetFailure
echo Errorlevel = %errorlevel%

pause

echo.
echo Calling ReturnErrorlevel.vbs
echo.

echo Calling with none parameter
cscript.exe /nologo ReturnErrorlevel.vbs
echo Errorlevel = %errorlevel%

echo Calling with SetOk parameter
cscript.exe /nologo ReturnErrorlevel.vbs SetOk
echo Errorlevel = %errorlevel%

echo Calling with SetFailure parameter
cscript.exe /nologo ReturnErrorlevel.vbs SetFailure
echo Errorlevel = %errorlevel%

endlocal

Simple.vbs - скрипт для проверки кодов возврата:

Dim objWshShell
Dim intRetCode

Set objWshShell = CreateObject("WScript.Shell")

WScript.Echo "Calling ReturnErrorlevel.cmd"

WScript.Echo "Calling with none parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.cmd", 1, True)
WScript.Echo "Errorlevel = " & intRetCode

WScript.Echo "Calling with SetOk parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.cmd SetOk", 1, True)
WScript.Echo "Errorlevel = " & intRetCode

WScript.Echo "Calling with SetFailure parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.cmd SetFailure", 1, True)
WScript.Echo "Errorlevel = " & intRetCode


WScript.Echo "Calling ReturnErrorlevel.vbs"

WScript.Echo "Calling with none parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.vbs", 1, True)
WScript.Echo "Errorlevel = " & intRetCode

WScript.Echo "Calling with SetOk parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.vbs SetOk", 1, True)
WScript.Echo "Errorlevel = " & intRetCode

WScript.Echo "Calling with SetFailure parameter"
intRetCode = objWshShell.Run("ReturnErrorlevel.vbs SetFailure", 1, True)
WScript.Echo "Errorlevel = " & intRetCode

Set objWshShell = Nothing

Результаты трудов.
Simple.cmd:

C:\Program Files\My Scripts\New>Simple.cmd

Calling ReturnErrorlevel.cmd

Calling with none parameter
Errorlevel = 2
Calling with SetOk parameter
Errorlevel = 0
Calling with SetFailure parameter
Errorlevel = 1
Для продолжения нажмите любую клавишу . . .

Calling ReturnErrorlevel.vbs

Calling with none parameter
Errorlevel = 2
Calling with SetOk parameter
Errorlevel = 0
Calling with SetFailure parameter
Errorlevel = 1

Simple.vbs:

C:\Program Files\My Scripts\New>cscript /nologo Simple.vbs
Calling ReturnErrorlevel.cmd

Calling with none parameter
Errorlevel = 0
Calling with SetOk parameter
Errorlevel = 0
Calling with SetFailure parameter
Errorlevel = 0

Calling ReturnErrorlevel.vbs

Calling with none parameter
Errorlevel = 2
Calling with SetOk parameter
Errorlevel = 0
Calling with SetFailure parameter
Errorlevel = 1

Причём, независимо от того, через cscript или wscript. Возможно, потому, что в данном случае происходит неявный (явный я тоже пробовал) вызов %comspec% и errorlevel получаем как раз от него, а не от батника?

2007-05-18 15:18:16

alexii пишет:

Так, нашёл в чём дело: в ReturnErrorlevel.cmd exit /b поменять на exit
ReturnErrorlevel.cmd

@echo off
setlocal ENABLEEXTENSIONS

if /i "%~1%"=="SETFAILURE" (
    exit 1
) else (
    if /i "%~1%"=="SETOK" (
        exit 0
    ) else (
        exit 2
    )
)

endlocal

После чего Simple.vbs отрабатывает правильно и при вызове cmd файла... Но, соответственно, перестаёт правильно работать Simple.cmd ...

2

Re: CMD: Код возврата командного файла при запуске из внешнего приложения

А приемлимое решение лежит рядом:
1) явно указывать обработчик командных файлов, т.е. CMD.EXE;
2) запускать командные файлы с помощью команды CALL


intRetCode = objWshShell.Run("cmd /c call ReturnErrorlevel.cmd ...", 1, True)

То же самое относится и к случаю запуска одного командного файла из другого в новом процессе (например, если надо задать ключи CMD.EXE для вызываемого файла) — в этом случае возврат в вызывающий файл произойдёт и без CALL, но вот код возврата будет упущен. Попробуйте в Simple.cmd заменить

call ReturnErrorlevel.cmd ...

сначала на

cmd /c ReturnErrorlevel.cmd ...

а потом на

cmd /c call ReturnErrorlevel.cmd ...