1

The below code is working fine for ping stackoverflow.com and most other cases but when I using 7z.exe it's not real time, it waits until directory is compressed and then shows the output. The argument that I used for compress is a test.7z dirpath. Can I do anything else?

    private ProcessStartInfo GetProcessStartInfo(string filename, string arguments)
    {
        ProcessStartInfo ProcessStartInfo = new ProcessStartInfo();
        ProcessStartInfo.CreateNoWindow = true;
        ProcessStartInfo.UseShellExecute = false;
        ProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        ProcessStartInfo.RedirectStandardOutput = true;
        ProcessStartInfo.RedirectStandardError = true;
        ProcessStartInfo.RedirectStandardInput = true;
        ProcessStartInfo.FileName = filename;
        ProcessStartInfo.Arguments = arguments;
    }

    private void ProcessRun(string filename, string arguments)
    {
        Process Process = new Process();
        Process.StartInfo = GetProcessStartInfo(filename, arguments);
        Process.ErrorDataReceived += Process_OutputDataReceived;
        Process.OutputDataReceived += Process_OutputDataReceived;
        Process.EnableRaisingEvents = true;
        Process.Start();
        Process.BeginOutputReadLine();
        Process.BeginErrorReadLine();

        Process.WaitForExit();
    }

    public ObservableList<string> Output = new ObservableList<string>();

    private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Output.Add(e.Data);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        OutputListBox.ItemsSource = Output;
        ProcessRun("cmd.exe", "/c ping stackoverflow.com");
    }

7zip Output:

enter image description here

7zip Progress:

enter image description here

Almis
  • 3,684
  • 2
  • 28
  • 58
  • And what is 7Z outputting? Is it perchance not putting out a newline until it's completed? – Matthew Watson Aug 27 '15 at 11:12
  • @MatthewWatson when directory is very small it doesn't show percentage only the above message see edits, otherwise it shows percentage progress on the same line and then again the same with above message. – Almis Aug 27 '15 at 11:20
  • That's the problem then - `OutputDataReceived` is only raised when a newline is written to the output. – Matthew Watson Aug 27 '15 at 11:27
  • @MatthewWatson but I not getting either the first lines, I get only the final output when everything finishes. – Almis Aug 27 '15 at 11:28

1 Answers1

1

If you're interested in the percentage, you're out of luck - that isn't done by standard output. Standard output only handles streams of data, while the percentage output is actually done by manipulating the console directly. It's not part of the output stream - there is no way to replicate the same effect using the standard I/O streams.

So it's not a problem of your code. If you want to see the same problem using just the Command prompt, try running this:

7z.exe yourarguments > log.txt

The > is an output redirect - instead of writing to the console, the standard output is redirected to a file. When you use it with ping, it immediately prints out standard output as it comes. When you use it with 7zip, you get the same result as with your C# application.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Yes you right, I wanted the percentage or at least to not show blank page while compressing.. It should show at least the first lines before progress – Almis Aug 27 '15 at 11:29
  • @Almis Yes, but those lines are never emitted into standard output until the compression is done. There's no way your application can get to them unless you write your own console and inject it into 7zip. – Luaan Aug 27 '15 at 11:30
  • Oh after your edits I understood why it doesn't. Any other way to achieve that? Hacky way? – Almis Aug 27 '15 at 11:31
  • @Almis Well, 7zip is open source - if you can deal with LGPL, the easiest way might be to simply change the way 7z prints out the status. It's also possible to use DLL hooks to redirect all console operations to you, but not in managed code - you'd have to do it in an unmanaged helper application; and of course, it's kind of fragile and dangerous. – Luaan Aug 27 '15 at 11:34
  • @Almis If that's not an option for you, and you don't mind showing an actual console, you can use P/Invoke to call `AllocConsole` (and get rid of it afterwards), which will then be used by whatever process you run. Or even just let it run with its own console. – Luaan Aug 27 '15 at 11:41
  • Yeah seems the best way, or somehow calculate the approximate time. Anyway thank you for your help :) – Almis Aug 27 '15 at 11:43