我正在运行一个程序,想看看它的返回代码是什么(因为它根据不同的错误返回不同的代码)。

我知道在巴斯我可以通过跑步来实现

echo $ ?

在Windows上使用cmd.exe时如何处理?


“退出代码”存储在一个名为errorlevel的shell变量中。

使用if命令关键字errorlevel进行比较:

if errorlevel <n> (<statements>)

当errorlevel大于或等于n时执行语句。如果/?获取详细信息。

名为errorlevel的shell变量以字符串形式包含该值,可以通过使用%'s进行包装来解除引用。

示例脚本:

my_nifty_exe.exe

rem Give resolution instructions for known exit codes.
rem Ignore exit code 1.
rem Otherwise give a generic error message.

if %errorlevel%==7 (
   echo "Replace magnetic tape."
) else if %errorlevel%==3 (
   echo "Extinguish the printer."
) else if errorlevel 2 (
   echo Unknown Error: %errorlevel% refer to Run Book documentation.
) else (
   echo "Success!"
)

警告:名为errorlevel的环境变量(如果存在)将覆盖名为errorlevel的shell变量。如果错误级别测试不受影响。


使用内置的ERRORLEVEL变量:

echo %ERRORLEVEL%

但是如果应用程序定义了一个名为ERRORLEVEL!


当使用未连接到控制台的程序时,它可能无法正常工作,因为当您认为拥有退出代码时,该应用程序可能仍在运行。 在c++中这样做的解决方案如下:

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "tchar.h"
#include "stdio.h"
#include "shellapi.h"

int _tmain( int argc, TCHAR *argv[] )
{

    CString cmdline(GetCommandLineW());
    cmdline.TrimLeft('\"');
    CString self(argv[0]);
    self.Trim('\"');
    CString args = cmdline.Mid(self.GetLength()+1);
    args.TrimLeft(_T("\" "));
    printf("Arguments passed: '%ws'\n",args);
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc < 2 )
    {
        printf("Usage: %s arg1,arg2....\n", argv[0]);
        return -1;
    }

    CString strCmd(args);
    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        (LPTSTR)(strCmd.GetString()),        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d)\n", GetLastError() );
        return GetLastError();
    }
    else
        printf( "Waiting for \"%ws\" to exit.....\n", strCmd );

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );
    int result = -1;
    if(!GetExitCodeProcess(pi.hProcess,(LPDWORD)&result))
    { 
        printf("GetExitCodeProcess() failed (%d)\n", GetLastError() );
    }
    else
        printf("The exit code for '%ws' is %d\n",(LPTSTR)(strCmd.GetString()), result );
    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return result;
}

测试ErrorLevel适用于控制台应用程序,但正如dmihailescu所暗示的,如果您试图从命令提示符运行一个窗口应用程序(例如基于win32的应用程序),这将不起作用。窗口化的应用程序将在后台运行,控制将立即返回到命令提示符(很可能带有一个ErrorLevel为零的错误级别,以指示进程已成功创建)。当窗口应用程序最终退出时,它的退出状态将丢失。

不过,与其使用其他地方提到的基于控制台的c++启动器,一个更简单的替代方法是使用命令提示符的start /WAIT命令启动窗口应用程序。这将启动窗口化应用程序,等待它退出,然后将控制返回到命令提示符,并在ErrorLevel中设置进程的退出状态。

start /wait something.exe
echo %errorlevel%

如果你想精确匹配错误代码(例如= 0),使用这个:

@echo off
my_nify_exe.exe
if %ERRORLEVEL% EQU 0 (
   echo Success
) else (
   echo Failure Reason Given is %errorlevel%
   exit /b %errorlevel%
)

请注意,如果errorlevel 0匹配errorlevel >= 0。 看是否/?

或者,如果你无法驾驭成功:

if  %ERRORLEVEL% NEQ 0 (
    echo Failed with exit-code: %errorlevel%
    exit /b %errorlevel%
)

有一次,我需要准确地将日志事件从Cygwin推送到Windows事件日志。我希望WEVL中的消息是自定义的,有正确的退出码、详细信息、优先级、消息等。所以我创建了一个Bash脚本来处理这个问题。这是GitHub上的logit.sh。

一些摘录:

usage: logit.sh [-h] [-p] [-i=n] [-s] <description>
example: logit.sh -p error -i 501 -s myscript.sh "failed to run the mount command"

下面是临时文件内容部分:

LGT_TEMP_FILE="$(mktemp --suffix .cmd)"
cat<<EOF>$LGT_TEMP_FILE
    @echo off
    set LGT_EXITCODE="$LGT_ID"
    exit /b %LGT_ID%
EOF
unix2dos "$LGT_TEMP_FILE"

下面是一个在WEVL中创建事件的函数:

__create_event () {
    local cmd="eventcreate /ID $LGT_ID /L Application /SO $LGT_SOURCE /T $LGT_PRIORITY /D "
    if [[ "$1" == *';'* ]]; then
        local IFS=';'
        for i in "$1"; do
            $cmd "$i" &>/dev/null
        done
    else
        $cmd "$LGT_DESC" &>/dev/null
    fi
}

执行批处理脚本并调用__create_event:

cmd /c "$(cygpath -wa "$LGT_TEMP_FILE")"
__create_event

值得注意的是,. bat和. cmd文件的操作方式不同。

阅读https://ss64.com/nt/errorlevel.html,它注意到以下几点:

There is a key difference between the way .CMD and .BAT batch files set errorlevels: An old .BAT batch script running the 'new' internal commands: APPEND, ASSOC, PATH, PROMPT, FTYPE and SET will only set ERRORLEVEL if an error occurs. So if you have two commands in the batch script and the first fails, the ERRORLEVEL will remain set even after the second command succeeds. This can make debugging a problem BAT script more difficult, a CMD batch script is more consistent and will set ERRORLEVEL after every command that you run [source].

当我执行连续的命令时,这导致了我无尽的悲伤,但即使在失败的情况下,ERRORLEVEL也会保持不变。