使用 from Process.StandardOuput 读取 7Zip 进度

Read 7Zip progress using from Process.StandardOuput

我正在从使用 7zip 提取和压缩存档的 System.Diagnostics.Process 重定向 Process.StandardOutputProcess.StandardError,但我无法从该过程中读取进度。

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

我尝试过的:

    var process = new Process
    {
        StartInfo =
                      {
                          FileName = command,
                          Arguments = arguments,
                          UseShellExecute = false,
                          RedirectStandardOutput = true,
                          RedirectStandardError = true
                      }
    };
    process.Start();

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

我试过异步事件处理程序:

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

我试过使用 StandardOutput 的异步方法:

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

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

并尝试使用底层基本流的异步方法。

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

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

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

这显示了直接在命令提示符中 运行ning 时的进度输出,每个成功的进度递增并覆盖前一个:

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

运行 相同的命令和参数使用 Process.Start()

    var process = new Process
    {
        StartInfo =
                      {
                          FileName = "c:\program files-zipz.exe",
                          Arguments = 'x -o"C:\target" \"K:\Disk_23339.secure.7z\"",
                          UseShellExecute = false,
                          RedirectStandardOutput = true,
                          RedirectStandardError = true
                      }
    };
    process.Start();
    process.StandardOutput.BaseStream.CopyToAsync(Console.OpenStandardOutput());
    process.WaitForExit();

当 运行 执行此操作并尝试读取进程字符的重定向标准输出时,这些字符不是从源进程发出的,不包含新行(通过换行或回车 return + 换行)输出到 System.Diagnostics.Process 的标准输出或标准错误,因此永远不会写入控制台。

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

是否可以从 Process.StandardOutputProcess.StandardError 中读取这些字符。

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

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

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

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

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

感谢@justintjacob How to show extraction progress of 7zip inside cmd?