title: Getting Batch Script Error Code
body: <p>I would like a Win32 process to launch an external script and be able to retrieve the ERRORLEVEL that it returns. </p>
  
  <p>The other way around is quite easy. Just use <strong>exit(errorcode)</strong> or <strong>return errorcode;</strong> in your Win32 app and the calling script gets its ERRORLEVEL value set properly.</p>
  
  <p>But, from a Win32 calling application, getting the script errorcode is not quite the same.</p>
  
  <p>I tried using CreateProcess() and calling GetExitCodeProcess(), but it always returns 0 and not the actual value of ERRORLEVEL. Even if I end my called script with <strong>exit %ERRORLEVEL%</strong></p>
  
  <p>My best guess is that a script is <em>not</em> a process per-say. Most probably CMD.EXE is running instead and most likely always ending with a ExitCode of 0. I know that ERRORLEVEL is not the same as the process ExitCode value, I would have hoped that CMD.EXE would have mirrored it.</p>
  
  <p>EDIT:</p>
  
  <p>Sorry I asked! I just found <strong>MY</strong> problem. I was using <strong>exit /b errorcode</strong> instead of <strong>exit errorcode</strong> in my batch file. It seems that the /b options has the advantage of only closing the running script, not CMD.EXE when you are testing from command line. But the disadvantage of not setting the proper ExitCode for CMD.EXE.</p>
  
  <p>So, for posterity what I am doing is:</p>
  
  <pre><code>int LaunchScript(TCHAR *pCmdLineParam)
  {
      bool bResult;
      PROCESS_INFORMATION pi;
      STARTUPINFO si;
  
      memset(&amp;si, 0, sizeof(si));
      si.cb = sizeof(si);
  
      TCHAR   cmdLine[256];
      _tcscpy(cmdLine,L"Test.cmd");
      _tcscat(cmdLine,L" ");
      _tcscat(cmdLine,pCmdLineParam);
  
      _tprintf(L"Process executing: %s\n",cmdLine);
  
      bResult = CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &amp;si, &amp;pi)?true:false;
      if (!bResult) {
          _tprintf(L"CreateProcess() error - %d", GetLastError());
          return -1;
      }
  
      DWORD result = WaitForSingleObject(pi.hProcess,15000);
      if( result == WAIT_TIMEOUT ) {
          return -2;
      }
  
      DWORD exitCode=0;
      if( !GetExitCodeProcess(pi.hProcess,&amp;exitCode) ) {
          _tprintf(L"GetExitCodeProcess() error - %d", GetLastError());
          return -1;
      }
  
      _tprintf(L"Process exitcode=%d\n",exitCode);
  
      return exitCode;
  }
  </code></pre>
  
  <p>My "entry point" batch file looks like:</p>
  
  <pre><code>@call %*
  @exit %ERRORLEVEL%
  </code></pre>
  
  <p>And I am passing my script to run as a parameter to the entry point script. The other "sub-scripts" files can either call exit /b or exit, because everything is covered.</p>