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

Posted

技术标签:

【中文标题】当 RedirectStandardOutput 为 true 时,tasklist 命令不会退出【英文标题】:tasklist command won't exit when RedirectStandardOutput is true 【发布时间】:2020-02-03 21:11:51 【问题描述】:

我正在尝试执行一个命令并等待它退出:

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;

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

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

有什么想法吗?

【问题讨论】:

proc.Start();proc.WaitForExit();之间插入console.WriteLine(proc.StandardOutput.ReadToEnd()); @JosefZ 添加 ReadToEnd() 有效。但我还需要限制使用proc.StandardOutput.Read() 读取的最大字节数。如果我在WaitForExit() 之前调用Read(),我将得到部分输出;如果我先做WaitForExit(),它会卡住 【参考方案1】:

您应该在调用WaitForExit() 之前阅读输出,此示例工作正常:

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;

不读取输出tasklist进程等待直到父进程读取输出,根据RedirectStandardOutput的备注部分

如果父进程调用可能会导致死锁情况 p.WaitForExitp.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 链接显示了一个示例)

【讨论】:

以上是关于当 RedirectStandardOutput 为 true 时,tasklist 命令不会退出的主要内容,如果未能解决你的问题,请参考以下文章

C#正在处理Linux命令输出

C++ 编写一个WIN32程序,向CMD传递参数

C# 做winform,在程序里选择文件(比如说word文档或图片),就直接调用对应程序打开该文件,如何实现啊!

当幸福来敲门英文PPT相关素材

python当密码正确输入,当密码错误时

更新:为啥当用户是管理员时关系有效,但当普通用户时不会?