Tyrrrz / CliWrap

Library for running command-line processes
MIT License
4.32k stars 264 forks source link

Ignore waiting for output stream when main process is finished, but it has active children reusing the same output streams #241

Open dmilosz opened 4 months ago

dmilosz commented 4 months ago

Details

When starting process which creates another process reusing the same window, CliWrap await ExecuteAsync() waits for entire processes tree to be finished, even when the main parent process is already finished.

Example reproduction:

Console.WriteLine($"Program started at: {DateTime.Now.ToLongTimeString()}");

var cmd = Cli.Wrap("powershell")
    .WithArguments("Start-Process -NoNewWindow -FilePath \"powershell\" -ArgumentList \"'sleep 5'\"; exit 0")
    .WithStandardOutputPipe(PipeTarget.ToDelegate(line => Console.WriteLine($"STDOUT {line}")))
    .WithStandardErrorPipe(PipeTarget.ToDelegate(line => Console.WriteLine($"STDERR {line}")));

var result = await cmd.ExecuteAsync();

Console.WriteLine($"Process started at: {result.StartTime.DateTime.ToLongTimeString()}");
Console.WriteLine($"Process finished with exit code: {result.ExitCode}");
Console.WriteLine($"Process finished at: {result.ExitTime.DateTime.ToLongTimeString()}");

Console.WriteLine($"Program finished at: {DateTime.Now.ToLongTimeString()}");

Output is:

Program started at: 12:23:49 PM
Process started at: 12:23:49 PM
Process finished with exit code: 0
Process finished at: 12:23:50 PM
Program finished at: 12:23:55 PM

But I'd like output to be:

Program started at: 12:23:49 PM
Process started at: 12:23:49 PM
Process finished with exit code: 0
Process finished at: 12:23:50 PM
Program finished at: 12:23:50 PM

So that it doesn't wait for dependent process to be finished, even if it uses the same output.

Currently there is no way to achieve this with CliWrap. Possible solution:

Add extra feature in CliWrap, so that it's possible to define that we don't want to wait for the output after process is finished:

var cmd = Cli.Wrap("powershell")
    .WithArguments("Start-Process -NoNewWindow -FilePath \"powershell\" -ArgumentList \"'sleep 5'\"; exit 0")
    .WithWaitingForOutputProcessing(false)
    .WithStandardOutputPipe(PipeTarget.ToDelegate(line => Console.WriteLine($"STDOUT {line}")))
    .WithStandardErrorPipe(PipeTarget.ToDelegate(line => Console.WriteLine($"STDERR {line}")));

I have already implemented solution in my fork and I can make a PR.

Checklist

Tyrrrz commented 4 months ago

Related: #185