当RedirectStandardOutput为true时,tasklist命令不会退出

时间:2019-10-06 06:44:45

标签: c# windows cmd process

我正在尝试执行命令并等待其退出:

Process proc = new Process();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.Start();

proc.WaitForExit();
return;

但是,如果tasklist设置为true,则RedirectStandardOutput命令永远不会退出。

如果我将RedirectStandardOutput设置为false或将命令更改为/c whoami,它将几乎立即退出。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

此代码段应该可以正常运行:

Process proc = new Process();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.Start();

var output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();

Console.WriteLine(output);
return;

根据MSDN,不读取输出tasklist的进程将等待直到父进程读取输出为止

  

如果父进程调用会导致死锁情况   p.WaitForExit之前的p.StandardOutput.ReadToEnd和子进程   写足够的文本以填充重定向的流。父进程   将无限期地等待子进程退出。孩子   进程将无限期地等待父级从全文中读取   StandardOutput流。

您还可以像这样异步读取进程输出(并限制进程等待退出超时)

Process proc = new Process();
StringBuilder output = new StringBuilder();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.OutputDataReceived += (s, e) =>
{
    output.Append(e.Data).Append("\n");
};
proc.ErrorDataReceived += (s, e) =>
{
    output.Append(e.Data).Append("\n");
};

proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit(100);

Console.WriteLine(output);

return; 

此外,如果您要重定向两个流(错误和输出),则至少要异步读取它们之一,这是由于再次发生了死锁(MSDN链接显示了一个示例)