简体   繁体   English

从命令行过程获取所需输出时出现问题

[英]Problems getting desired output from Command line process

I am trying to add Windows natives notifications for the lftp linux process. 我正在尝试为lftp linux进程添加Windows本机通知。 To do that I'm trying to launch the command from c# Console App to catch the status of lftp. 为此,我试图从c#控制台应用程序启动命令以捕获lftp的状态。 The problem is that I don't have the same output if I launch it from c# that if I run it from bash. 问题是,如果我从c#启动它与从bash运行它,则没有相同的输出。

I have an helper class to do my Command Line calls : 我有一个帮助器类来进行命令行调用:

public static class ShellHelper
{
    public static void Bash(this string cmd)
    {
        var escapedArgs = cmd.Replace("\"", "\\\"");

        var process = new Process()
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = "C:/cygwin64/bin/sh.exe",
                Arguments = $"-c \"{escapedArgs}\"",
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true,
                StandardOutputEncoding = Encoding.UTF8,
                WindowStyle = ProcessWindowStyle.Hidden,
            }
        };

        process.OutputDataReceived += new DataReceivedEventHandler(ReadOutput);
        process.ErrorDataReceived += new DataReceivedEventHandler(ErrorOutput);

        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        process.WaitForExit();
    }

    private static void ErrorOutput(object sender, DataReceivedEventArgs e)
    {
        if (e.Data != null)
        {
            Console.WriteLine("Error: " + e.Data);
        }
    }

    private static void ReadOutput(object sender, DataReceivedEventArgs e)
    {
        if (e.Data != null)
        {
            Console.WriteLine(e.Data);
        }
    }
}

And my call is : 我的电话是:

ShellHelper.Bash("unbuffer lftp -p 22 -u login,password sftp://XXXXXXXXX -e \"set mirror:use-pget-n 20; mirror --parallel=3 -c -P5 /home29/qualinost/files/tests ./tests; quit; \"");

This is the expected output that I get when I launch the command from bash 这是我从bash启动命令时获得的预期输出

cd `/home29/qualinost/files/tests' [Connecting...]
cd `/home29/qualinost/files/tests' [Connected]      
`Kaamelott - S01E17 - Le Signe.mkv', got 0 of 48941955 (0%)
    ............................................................................................................................................................................................................................................
[A`Kaamelott - S01E17 - Le Signe.mkv', got 32768 of 48941955 (0%)
................................................................................    ................................................................................    .............................................................................
[A`Kaamelott - S01E17 - Le Signe.mkv', got 131072 of 48941955 (0%)  
................................................................................    ................................................................................    .............................................................................
[A`Kaamelott - S01E17 - Le Signe.mkv', got 458752 of 48941955 (0%) 235.7K/s
oo..............................................................................    ................................................................................    .............................................................................
[A`Kaamelott - S01E17 - Le Signe.mkv', got 720896 of 48941955 (1%) 265.0K/s   

And this is what I get when I launch the same command from c# : 这就是我从c#启动相同命令时得到的:

cd `/home29/qualinost/files/tests' [Connecting...]
cd `/home29/qualinost/files/tests' [Connected]
`...1E17 - Le Signe.mkv', got 0 of 48941955 (0%)
`...1E17 - Le Signe.mkv', got 131072 of 48941955(0%)..........................
`...1E17 - Le Signe.mkv', got 917504 of 48941955 (1%) 598.5K/s.................
`...1E17 - Le Signe.mkv', got 1671168 of 48941955 (3%) 730.4K/s  ..............
`...1E17 - Le Signe.mkv', got 1900544 of 48941955 (3%) 734.7K/s   .............
`...1E17 - Le Signe.mkv', got 2588672 of 48941955 (5%) 650.1K/s   .............
`...1E17 - Le Signe.mkv', got 3473408 of 48941955 (7%) 727.3K/s   .............
`...1E17 - Le Signe.mkv', got 4096000 of 48941955 (8%) 718.8K/s   .............
`...1E17 - Le Signe.mkv', got 4816896 of 48941955 (9%) 747.9K/s   .............
`...1E17 - Le Signe.mkv', got 5668864 of 48941955 (11%) 954.0K/s  .............

As you can see the name of the file is truncate. 如您所见,文件名被截断。 My guess is it's maybe a buffer size problem or an encoding format problem with some specials chars that c# doesn't like. 我的猜测是它可能是缓冲区大小问题或某些c#不喜欢的特殊字符的编码格式问题。

I also tried to directly redirect the output in a file from the command like so: 我还尝试通过如下命令直接将输出重定向到文件中:

ShellHelper.Bash("unbuffer lftp -p 22 -u login,password sftp://XXXXXX -e \"set mirror:use-pget-n 20; mirror --parallel=3 -c -P5 /home29/qualinost/files/tests ./tests; quit; \" > output.log");

But it's the same, works like a charm from bash but missing parts when I launch from c#.. 但这是相同的,就像从bash中获得的魅力一样工作,但是当我从c#中启动时缺少了部分。

Any ideas on what's happening here? 关于这里发生的事情有什么想法吗?

EDIT : Someone posted a comment (and deleted it??) and pointed out that the maximum number of characters that "c#" give me by output line is 80. He asked me to resize the Console with 编辑:有人发表了评论(并删除了它??),并指出“ c#”输出行给我的最大字符数为80。他要求我使用

Console.SetWindowSize(400, 800);

at the begining of my program but it doesn't changed anything. 在我的程序开始时,但没有任何改变。 But the 80 chars max is probably an interresting remark! 但是最大80个字符可能是一个有趣的说法!

EDIT 2: I cleaned up the output of lftp with a sed command to remove the progress bar and only get the name of the file and it's progression. 编辑2:我用sed命令清理了lftp的输出,以删除进度条,仅获取文件名及其进度。 But still the output is truncate when I launch my script from C#. 但是当我从C#启动脚本时,输出仍然被截断。 I did a test with an extremly short file name (yo.mkv) and everything is here! 我用一个极短的文件名(yo.mkv)进行了测试,一切都在这里! So I think it's definitly a buffer size problem of StandardOutput. 所以我认为这绝对是StandardOutput的缓冲区大小问题。 Is there a way to define a bigger size of this buffer? 有没有办法定义此缓冲区的更大大小?

I finally found a workaround on this broken MS async output redirection. 我终于找到了关于此损坏的MS异步输出重定向的解决方法。 I used this code https://stackoverflow.com/a/13860551/1502444 to be able to read each chars of the output by using StandardOutput.Read() method in a different thread and changing the Read buffer size. 我使用此代码https://stackoverflow.com/a/13860551/1502444能够通过在不同线程中使用StandardOutput.Read()方法并更改读取缓冲区大小来读取输出的每个字符。 Would like to thanks the author of this solution and raterus to pointed out the async read problem. 感谢这个解决方案和raterus的作者指出了异步读取问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM