使用Process.StandardOuput读取7Zip进度

问题描述

我正在从Process.StandardOutput重定向Process.StandardErrorSystem.Diagnostics.Process,该 var process = new Process { StartInfo = { FileName = command,Arguments = arguments,UseShellExecute = false,RedirectStandardOutput = true,RedirectStandardError = true } }; process.Start(); 使用7zip提取和压缩归档文件,并且无法从该过程中读取进度。

似乎7Zip像其他一些应用程序一样,发出退格键并删除字符以部分写入行数据,然后使用退格键删除所写入的字符并按顺序删除显示进度。我试图从目标进程中读取那些部分行的输出,但无法做到这一点。但是,在这个假设中我可能是错的。

我尝试过的事情:

    process.OutputDataReceived += (sender,args) => { Console.WriteLine(args.Data); };
    process.ErrorDataReceived += (sender,args) => { Console.WriteLine(args.Data); };
    process.BeginoutputReadLine();
    process.BeginErrorReadLine();

在上面的代码块之后,我尝试使用各种方法读取数据。

我尝试了异步事件处理程序:

    while (!process.StandardOutput.EndOfStream)
    {
        char[] buffer = new char[256];
        int read = process.StandardOutput.ReadAsync(buffer,buffer.Length).Result;
        Console.Write(buffer,read);
    }

我尝试使用StandardOutput的异步方法

    process.StandardOutput.BaseStream.copyToAsync(Console.OpenStandardOutput());

    while (!process.StandardOutput.EndOfStream)
    {
        byte[] buffer = new byte[256];
        int read = process.StandardOutput.BaseStream.ReadAsync(buffer,buffer.Length).Result;
        string data = Encoding.UTF8.GetString(buffer,read);
        Console.Write(data);
    }

并尝试使用基础基本流的异步方法

"c:\program files\7-zip\7z.exe" x -o"C:\target" "K:\disk_23339.secure.7z"

例如,使用以下命令从终端运行7Zip:

Process.Start()

这将显示直接在命令提示符下运行时的进度输出,每个成功进度将递增以覆盖先前的进度:

7Zip shows progress in the output terminal

然后使用退格字符覆盖先前的进度。

7Zip updated progress in the output terminal

使用 var process = new Process { StartInfo = { FileName = "c:\program files\7-zip\7z.exe",Arguments = 'x -o"C:\target" \"K:\disk_23339.secure.7z\"",RedirectStandardError = true } }; process.Start(); process.StandardOutput.BaseStream.copyToAsync(Console.OpenStandardOutput()); process.WaitForExit();

运行相同的命令和参数
System.Diagnostics.Process

运行此命令并尝试读取未从源进程发出的不包含新行的过程字符的重定向标准输出(通过换行或回车+换行),将输出到标准输出或标准错误Process.StandardOutput,因此永远不会写入控制台。

7Zip standard output redirection does not show progress characters overwritten with backspaces

7zip当然只是一个例子。许多PowerShell和Python脚本也会发生此问题。

反正可以从Process.StandardError {% if blog.content|length > 500 %} 读取这些字符。

我不确定,但是我认为问题是底层的流阅读器一次读取一行,并且从不返回这些部分行,因为它们从不包含行结束符。

解决方法

虽然帖子已经发布了几个月,但如果您的问题(在命令行中执行时无法从 7zip 获得进度)仍然存在,请在命令行参数中使用“-bsp1”开关。

我也在寻找相同问题的解决方案并且刚刚得到它(在我的情况下成功测试)。通过重定向StandardOutput,重复执行cmd.StandardOutput.ReadLine()(同步方法,我测试了这个方法而不是使用EventHandler的异步方法,但我认为异步方法也可以),并使用RegExp检测进度以更新我的用户界面。

我的命令(在 .NET 中运行)

C:\Program Files\7-Zip\7z.exe a -t7z -mx=9 -bsp1 "G:\Temp\My7zTest_Compressed.7z" "G:\SourceFolder"

归功于@justintjacob How to show extraction progress of 7zip inside cmd?