C# 从命令行进程获取所需输出时出现问题
我正在尝试为lftp linux进程添加Windows本机通知。 为此,我尝试从c#控制台应用程序启动命令,以捕获lftp的状态。 问题是,如果从c#启动它,我的输出与从bash运行它的输出不一样 我有一个助手类来执行命令行调用:C# 从命令行进程获取所需输出时出现问题,c#,bash,command-line,C#,Bash,Command Line,我正在尝试为lftp linux进程添加Windows本机通知。 为此,我尝试从c#控制台应用程序启动命令,以捕获lftp的状态。 问题是,如果从c#启动它,我的输出与从bash运行它的输出不一样 我有一个助手类来执行命令行调用: public static class ShellHelper { public static void Bash(this string cmd) { var escapedArgs = cmd.Replace("\"", "\\\"
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);
}
}
}
我的电话是:
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; \"");
这是我从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
这就是我从c#启动相同命令时得到的结果:
如您所见,文件名为truncate。
我猜这可能是缓冲区大小问题,或者是一些c#不喜欢的特殊字符的编码格式问题
我还尝试从命令直接重定向文件中的输出,如下所示:
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");
但它是一样的,就像bash的魅力一样,但当我从c#启动时,它缺少了一些部分
你知道这里发生了什么吗
编辑:有人发布了一条评论(并将其删除了???),并指出“c#”在输出行中给我的最大字符数是80。他让我用鼠标调整控制台的大小
Console.SetWindowSize(400, 800);
在我的程序开始时,但它没有改变任何事情。但80个字符的最大值可能是一个令人发问的评论
edit2:我用sed命令清除了lftp的输出,以删除进度条,只获取文件名及其进度。但当我从C#启动脚本时,输出仍然被截断。
我用一个非常短的文件名(yo.mkv)做了一个测试,一切都在这里!所以我认为这肯定是StandardOutput的缓冲区大小问题。有没有办法定义一个更大的缓冲区大小?我终于找到了一个解决办法,解决了这个中断的MS异步输出重定向问题。 我使用这段代码能够通过在不同的线程中使用StandardOutput.read()方法并更改读取缓冲区大小来读取输出的每个字符。
感谢此解决方案的作者和raterus指出异步读取问题。我刚刚尝试添加:Console.setWindowsSize(400800);在打电话之前但什么都没变。。。这可能是一个好方法,因为截断文件名前的3个点“…”可能是因为它无法显示整个字符串…我相信你的问题是由于进度条,这些进度条使用了很多控制字符,很难在标准输出中捕获,因为它们在不断变化。你有没有看过这个工具“unbuffer”的日志选项,看看是否有一种方法可以设置一个不使用进度条的更标准的日志记录?遗憾的是,我没有lftp输出。unbuffer只是我添加到cygwin的expect包中的一个脚本。它允许我解除lftp的“动态”输出缓冲。在C#中,反勾号是否可能是流输出中的问题?在完整的输出中,我可以看到我总是在剪切之前有这些字符[A`?在这里丢失异步读取(BeginOutputReadLine),并使用Read()方法直接处理ProcessInfo.StandardOutput流。请参阅:读取缓冲区大小是关键!不再使用10240(10k)缓冲区(而不是1k)截断输出。
Console.SetWindowSize(400, 800);