your programing

Windows 명령 줄에서 애플리케이션 종료 코드를 얻으려면 어떻게해야합니까?

lovepro 2020. 9. 29. 08:18
반응형

Windows 명령 줄에서 애플리케이션 종료 코드를 얻으려면 어떻게해야합니까?


프로그램을 실행 중이며 반환 코드가 무엇인지 확인하고 싶습니다 (다른 오류에 따라 다른 코드를 반환하기 때문에).

나는 Bash에서 실행함으로써 이것을 할 수 있다는 것을 안다.

에코 $?

Windows에서 cmd.exe를 사용할 때 어떻게해야합니까?


라는 의사 환경 변수 errorlevel는 종료 코드를 저장합니다.

echo Exit Code is %errorlevel%

또한 if명령에는 특수 구문이 있습니다.

if errorlevel

자세한 내용은 if /?을 참조하십시오.

@echo off
my_nify_exe.exe
if errorlevel 1 (
   echo Failure Reason Given is %errorlevel%
   exit /b %errorlevel%
)

경고 : 환경 변수 이름을 설정하면 errorlevel, %errorlevel%그 값이 아닌 종료 코드를 반환합니다. ( set errorlevel=)를 사용 하여 환경 변수를 지우면 환경 변수를 errorlevel통해의 실제 값에 액세스 할 수 있습니다 %errorlevel%.


테스트 ErrorLevel콘솔 응용 프로그램에서 작동 하지만 dmihailescu 에서 암시 했듯이 명령 프롬프트에서 응용 프로그램 (예 : Win32 기반) 을 실행하려는 경우에는 작동하지 않습니다 . 창 응용 프로그램은 백그라운드에서 실행되고 제어는 즉시 명령 프롬프트로 돌아갑니다 (대부분 ErrorLevel프로세스가 성공적으로 생성 되었음을 나타내는 0 으로 표시됨). 창 응용 프로그램이 결국 종료되면 종료 상태가 손실됩니다.

그러나 다른 곳에서 언급 한 콘솔 기반 C ++ 런처를 사용하는 대신 더 간단한 대안은 명령 프롬프트의 START /WAIT명령을 사용하여 창 응용 프로그램을 시작하는 것 입니다. 이렇게하면 창 응용 프로그램이 시작되고 종료 될 때까지 기다린 다음에 설정된 프로세스의 종료 상태와 함께 명령 프롬프트에 제어가 반환됩니다 ErrorLevel.

start /wait something.exe
echo %errorlevel%

내장 된 ERRORLEVEL 변수를 사용하십시오.

echo %ERRORLEVEL%

그러나 응용 프로그램이 ERRORLEVEL이라는 환경 변수를 정의했는지주의하십시오 !


오류 코드를 정확히 일치 시키려면 (예 : 0과 같음) 다음을 사용하십시오.

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

if errorlevel 0errorlevel> = 0 과 일치 합니다 if /?.를 참조하십시오 .


콘솔에 연결되지 않은 프로그램을 사용하면 종료 코드가 있다고 생각하는 동안 해당 앱이 계속 실행될 수 있으므로 제대로 작동하지 않을 수 있습니다. 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;
}

It's worth noting that .BAT and .CMD files operate differently.

Reading https://ss64.com/nt/errorlevel.html it notes the following:

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].

This was causing me no end of grief as I was executing successive commands, but the ERRORLEVEL would remain unchanged even in the event of a failure.


At one point I needed to accurately push log events from Cygwin to the Windows Event log. I wanted the messages in WEVL to be custom, have the correct exit code, details, priorities, message, etc. So I created a little Bash script to take care of this. Here it is on GitHub, logit.sh.

Some excerpts:

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"

Here is the temporary file contents part:

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"

Here is a function to to create events in 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
}

Executing the batch script and calling on __create_event:

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

참고URL : https://stackoverflow.com/questions/334879/how-do-i-get-the-application-exit-code-from-a-windows-command-line

반응형