Process
类来启动进程。您还可以读取它的stdout和stderr流,并向stdin写入一些内容。您可以等待进程在指定的时间内退出。问题是,它需要大量的代码,但仍然不能在所有情况下都正常工作。
异步读取应该可以解决“缓冲区已满”的阻塞问题,但不能告诉您什么时候有所有的输出。它可能会在开始时错过一些输出。
This question
投票率最高的所有评论都很好地概括了各种各样的问题。
因此,我正在寻找一种能够:
-
用参数启动进程
-
让我把数据发送到它的输入
-
-
等待指定的时间,如果进程没有及时返回,则终止进程
-
当我得到最终结果(超时/退出代码和到目前为止的所有输出)时,让我继续
Windows和Linux上的.NET Core 3.1的2020版。
异步等待进程也很好。我有
some
code
为此,还有一次,它的作用是巨大的。
这是我现在所拥有的,但它对于更大的输出是不起作用的:(进程不会退出,需要终止)
var psi = new ProcessStartInfo
{
FileName = "dotnet",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
psi.ArgumentList.Add("--list-runtimes"); // A few pages output on my PC
string standardOutput;
string standardError;
using (var process = Process.Start(psi))
{
bool timedOut = false;
// Sync version
if (!process.WaitForExit(10000))
{
try
{
// Try to clean things up
process.Kill();
}
catch
{
// Might have exited after all during the short period of time before
// calling Kill(). And if it fails for other reasons, we can't help it here.
}
timedOut = true;
}
// BEGIN Async alternative
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
try
{
await process.WaitForExitAsync(cts.Token);
}
catch (OperationCanceledException ex) when (ex.CancellationToken == cts.Token)
{
try
{
// Try to clean things up
process.Kill();
}
catch
{
// Might have exited after all during the short period of time before
// calling Kill(). And if it fails for other reasons, we can't help it here.
}
timedOut = true;
}
// END Async alternative
standardOutput = process.StandardOutput.ReadToEnd();
standardError = process.StandardError.ReadToEnd();
if (timedOut)
{
logger?.LogError($"The command did not complete in time.\n" +
$"Output: {standardOutput.TrimEnd()}\nError: {standardError.TrimEnd()}");
standardOutput = null;
}
else if (process.ExitCode != 0)
{
logger?.LogError($"The command failed with exit code {process.ExitCode}.\n" +
$"Output: {standardOutput.TrimEnd()}\nError: {standardError.TrimEnd()}");
standardOutput = null;
}
}