it-swarm.asia

كيف يمكنني الحصول على رمز خروج التطبيق من سطر أوامر Windows؟

أقوم بتشغيل برنامج وأريد أن أرى ما هو رمز الإرجاع الخاص به (لأنه يُرجع رموزًا مختلفة بناءً على أخطاء مختلفة).

أعرف في باش يمكنني القيام بذلك عن طريق الجري

صدى $؟

ماذا أفعل عند استخدام cmd.exe على Windows؟

708
Skrud

يقوم متغير البيئة الزائفة المسمى 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%.

863
Samuel Renkert

يعمل اختبار ErrorLevel على وحدة التحكم التطبيقات ، ولكن كما تم التلميح عند بواسطة dmihailescu ، لن ينجح هذا إذا كنت تحاول تشغيل windowed application (مثل Win32- ) من موجه الأوامر. سيتم تشغيل التطبيق الموجود في إطارات في الخلفية ، وسيعود التحكم فورًا إلى موجه الأوامر (على الأرجح مع ErrorLevel من الصفر للإشارة إلى أن العملية كانت تم إنشاؤها بنجاح). عندما يتم إنهاء تطبيق في نهاية المطاف ، يتم فقد حالة الخروج الخاصة به.

بدلاً من استخدام مشغل C++ المستند إلى وحدة التحكم والمشار إليه في مكان آخر ، على الرغم من ذلك ، فإن البديل الأكثر بساطة هو بدء تشغيل تطبيق في إطارات باستخدام أمر موجه الأوامر START /WAIT. سيؤدي هذا إلى بدء تشغيل التطبيق المحدد في إطارات ، وانتظر حتى يتم الخروج منه ، ثم يُرجع عنصر التحكم إلى الأمر مطالبة بحالة الخروج من العملية المحددة في ErrorLevel.

start /wait something.exe
echo %errorlevel%
227
Gary

استخدم متغير ERRORLEVEL المدمج:

echo %ERRORLEVEL%

ولكن احذر إذا قام أحد التطبيقات بتعريف متغير بيئة يسمى ERRORLEVEL !

92
Adam Rosenfield

إذا كنت تريد مطابقة رمز الخطأ تمامًا (على سبيل المثال يساوي 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 0 التطابقات errorlevel> = 0. راجع if /?.

18
Curtis Yallop

قد لا يعمل بشكل صحيح عند استخدام برنامج غير مرفق بوحدة التحكم ، لأن هذا التطبيق قد لا يزال قيد التشغيل بينما تعتقد أن لديك رمز الخروج. حل للقيام بذلك في 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;
}
14
dmihailescu

تجدر الإشارة إلى أن ملفات .BAT و .CMD تعمل بشكل مختلف.

قراءة https://ss64.com/nt/errorlevel.html تلاحظ ما يلي:

هناك فرق رئيسي بين الطريقة .CMD و .BAT الملفات الدفعية تعيين errorlevels:

سيناريو دفعي .BAT قديم يشغل الأوامر الداخلية "الجديدة": APPEND و ASSOC و PATH و Prompt و FTYPE و SET لن يقوم بتعيين ERRORLEVEL إلا في حالة حدوث خطأ. لذلك إذا كان لديك أمرين في البرنامج النصي الدفعي وفشل الأول ، فسيظل ERRORLEVEL مضبوطًا حتى بعد نجاح الأمر الثاني.

قد يؤدي ذلك إلى جعل تصحيح أخطاء النص البرمجي BAT للمشكلة أكثر صعوبة ، البرنامج النصي للدفعة CMD أكثر تناسقًا وسيعين ERRORLEVEL بعد كل أمر تقوم بتشغيله [source].

هذا لم يسبب لي نهاية للحزن لأنني كنت أنفذ الأوامر المتتالية ، لكن ERRORLEVEL سيبقى كما هو حتى في حالة الفشل.

5
RockDoctor

عند نقطة واحدة كنت بحاجة إلى دفع أحداث السجل بدقة من Cygwin إلى سجل أحداث Windows. أردت أن تكون الرسائل في WEVL مخصصة ، وأن يكون لديك كود الخروج الصحيح ، والتفاصيل ، والأولويات ، والرسالة ، إلخ. لذلك قمت بإنشاء نص برمجي صغير لأتولى هذا. ومن هنا على جيثب ، 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
0
jonretting