Search code examples
c#winformsbatch-filebackgroundworkererrorlevel

Different behaviour when using a command line script or running it from a backgroundworker


I have a really weird problem which recquire a strong knowledge of C# 's backgroundworker.

I want to run a command line program and check its ERRORLEVEL.

cmd.exe /c echo Launching the command && COMMAND_TO_RUN & echo Connexion statut : && echo %ERRORLEVEL% && if %ERRORLEVEL% NEQ 0 (echo FAILURE) ELSE (echo SUCCESS))

When the command fail, the ERRORLEVEL get the value -1

This works when I use this line in the cmd.exe.

But, here is the problem.

When I use a background worker to run this line, the ERRORLEVEL take the value 0 even if the COMMAND_TO_RUN fail.

Here is my backgroundworker code :

string[] args = { "/c echo Launching the command && COMMAND_TO_RUN  & echo Connexion statut : && echo %ERRORLEVEL% && if %ERRORLEVEL% NEQ 0 (echo FAILURE) ELSE (echo SUCCESS))};
backgroundWorker1.RunWorkerAsync(args);


 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        string[] args = e.Argument as string[];
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.FileName = "cmd.exe";
        process.StartInfo.Arguments = args[0];
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardInput = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = false;
        process.Start();
        System.IO.StreamReader sOut = process.StandardOutput;

        string tempOut;
        while (!sOut.EndOfStream)
        {
            // using the report progress userstate allow me to catch 
            // the program output in runtime
            tempOut = sOut.ReadLine();
            backgroundWorker1.ReportProgress(1, tempOut);
        }
        process.Close();
    }

So Does the use of a backgroundworker lead to a particular value of the ERRORLEVEL ?

Thanks in advance


Solution

  • Without knowing anything about BackgroundWorker (sorry), there are at least three problems with the command part:

    1. Depending on the real COMMAND_TO_RUN, maybe it is not executed inside the cmd spawned instance and, independtly of it, the spawned cmd instance has ended its execution without problems so the errorlevel you get in your C# code, the exit code from cmd, can be 0.

    2. When the line is readed by cmd, it is parsed and then executed. In the parse phase, all the variable read operations are removed from the command to be executed and replaced by the value inside the variable before starting to execute the line. So, all your %errorlevel% reads (that are all in the same line) do not change when you run your COMMAND_TO_RUN and will return the value in the variable before the command execution.

    3. There is a concatenation problem. A & B is used to concatenate command execution, that is, run A, when finished run B. But A && B means run A and if not errorlevel then run B (A && B || C means run A, if not errorlevel run B, else run C)

    Try with something like this (dir is the command that will fail)

    cmd.exe /c "echo Launching the command & (( dir *.notexist >nul 2>nul  )&&( echo SUCCESS & exit /b 0 )||( echo FAILURE & exit /b 1 ))"