Process.Start 将流留空

本文关键字:Start Process | 更新日期: 2023-09-27 18:32:49

我有运行控制台命令/实用程序的代码,使用"Debug.WriteLine"监视实时输出,并在需要时将最终输出写入日志文件。

编辑:它不适用于分析命令行实用程序Praatcon.exe。可以从这里下载。只需调用praatcon.exe没有争论,它应该写在"stdout"上关于用法。代码不会捕获它。

问题是,它适用于某些实用程序,我可以看到调试输出以及登录文件。但是对于某些实用程序,我看到空命令,即使当我通过CMD窗口运行这些命令时,我也会看到输出。我正在捕获流输出和错误。

有人可以帮助我吗?

完整的代码可以在这里找到

这是我尝试的方式

进程启动信息的初始化

        var info = new ProcessStartInfo(command, parameters)
        {
            WorkingDirectory = workingDirectory,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        };

运行进程并初始化输出和错误流的字符串生成器。

        var process = Process.Start(info);
        var output = new StringBuilder();
        var error = new StringBuilder();

启动读取流的任务

        var errorTask = process.StandardError.ReadLineAsync();
        var lineTask = process.StandardOutput.ReadLineAsync();

这是我的 while 循环,用于监视进度并在有可用时将输出写入"调试输出"窗口。

            while (process.HasExited == false)
            {
                if (lineTask.IsCompleted)
                {
                    output.AppendLine(lineTask.Result);
                    Debug.WriteLine(lineTask.Result);
                    lineTask = process.StandardOutput.ReadLineAsync();
                }
                if (errorTask.IsCompleted)
                {
                    error.AppendLine(errorTask.Result);
                    Debug.WriteLine(errorTask.Result);
                    errorTask = process.StandardError.ReadLineAsync();
                }
                errorTask.Wait(TimeSpan.FromMilliseconds(100.0));
                lineTask.Wait(TimeSpan.FromMilliseconds(100.0));
            }

在此之后,我正在进一步阅读溪流,看看那里是否还剩下任何东西。

我在输出中得到空字符串和一个命令的错误。我唯一正确的是"退出代码"。

请告诉我是否有我做错了什么。

Process.Start 将流留空

正如在IRC上讨论的那样,您调用的程序可能正在写入标准输出或标准错误以外的流。Windows上也有数字为3-9的流。

您调用的进程并非如此。它实际上是使用Win32调用"WriteConsole",它似乎直接访问控制台。

可以通过

预加载 DLL(DLL 注入(将输出移回 stdrr,但这是黑客,因此当程序的源代码可用时,最好"修复"它或向作者提交补丁。

你的问题过于宽泛,因为它缺少细节,"我做错了什么"是相当开放的。

也就是说,您以

错误的方式读取流,从某种意义上说,您不应该进行轮询。我没有看到任何具体的原因会导致你(模糊地(描述的行为。但为了以防万一,我提供了这个正确的阅读实现:

async Task ConsumeStream(StreamReader reader, StringBuilder builder)
{
    string line;
    while ((line = await reader.ReadLineAsync()) != null)
    {
        builder.AppendLine(line);
        Debug.WriteLine(line);
    }
}

然后像这样调用该方法:

var errorTask = ConsumeStream(process.StandardError, error);
var lineTask = ConsumeStream(process.StandardOutput, output);
// Technically superfluous, since you'll also wait on the tasks,
// but won't hurt.
process.WaitForExit();
Task.WaitAll(errorTask, lineTask);
// error and output StringBuilders will be valid here

如果这没有帮助,你需要发布一个更好的代码示例,这将允许其他人重现实际问题。请参阅 https://stackoverflow.com/help/mcve