Skip to content

Unexpected WaitForExit behavior when using cmd.exe with the start command #103384

Open

Description

Description

When using output redirection, along with the start command, WaitForExit() does not properly detect the exit.

See the following code:

process.StartInfo = new ProcessStartInfo()
{
    FileName = "cmd.exe",
    Arguments = "/C " + $"\"start cmd /c \"echo test && timeout /t 3\"\"",
    UseShellExecute = false,
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    CreateNoWindow = true
};

process.OutputDataReceived += ProcessOnOutputDataReceived;
process.ErrorDataReceived += ProcessOnErrorDataReceived;

_stopwatch.Start();

Console.WriteLine("Starting process...");

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

process.WaitForExit();

Console.WriteLine($"Process exited: {_stopwatch.ElapsedMilliseconds}");
Console.ReadLine();

The output is as follows:

Starting process...
OUT (3062): NULL
ERR (3062): NULL
Process exited: 3062

You can see that it waits for the second 3 second cmd process finishes, even though it should return immediately after the original cmd.exe exits.

However, if either a timeout is provided to WaitForExit, or redirection is not enabled, it will return as expected:

process.WaitForExit(60000);

Output:

Starting process...
Process exited: 26
ERR (3171): NULL
OUT (3171): NULL

Note that the output still does not return null until the second cmd process exits.

Reproduction Steps

public static void Run()
{
    var process = new Process();
    process.StartInfo = new ProcessStartInfo()
    {
        FileName = "cmd.exe",
        Arguments = "/C " + $"\"start cmd /c \"echo test && timeout /t 3\"\"",
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    };
    process.OutputDataReceived += ProcessOnOutputDataReceived;
    process.ErrorDataReceived += ProcessOnErrorDataReceived;
    
    var stopwatch = new Stopwatch();
    stopwatch.Start();

    Console.WriteLine("Starting process...");

    process.Start();
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();
    
    process.WaitForExit();
    
    Console.WriteLine($"Process exited: {stopwatch.ElapsedMilliseconds}");
    Console.ReadLine();
}
private static void ProcessOnErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine("ERR: " + (e.Data ?? "NULL"));
}

private static void ProcessOnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine("OUT: " + (e.Data ?? "NULL"));
}

Expected behavior

WaitForExit() should return once the first cmd process exits, and likewise OutputDataReceived/ErrorDataReceived should send null.

Configuration

Windows 11 x64
.NET 8.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions