1

rsync从我的应用程序内部启动。现在它工作正常,它打开一个控制台窗口,提示我输入密码,并在文件复制时显示文件进度。

public static int SyncFolder(string sourceFolder, string destFolder)
{

    Process rsync = new Process();
    rsync.StartInfo.FileName = Path.Combine(RsyncPath, "rsync.exe");
    rsync.StartInfo.UseShellExecute = true;
    rsync.StartInfo.Arguments = String.Join(" ", new[] { "-rltzh --progress --chmod=a=rw,Da+x", FileUtils.EncodeParameterArgument(sourceFolder), FileUtils.EncodeParameterArgument(destFolder) });
    rsync.Start();
    rsync.WaitForExit();

    return rsync.ExitCode;
}

问题是我不想打开单独的控制台窗口。我想在某种类型的控件中显示文本进度,并从我的程序本身内部响应任何提示(例如输入密码)。

public int SyncFolder(string sourceFolder, string destFolder)
{

    Process rsync = new Process();
    rsync.StartInfo.FileName = Path.Combine(RsyncPath, "rsync.exe");
    rsync.StartInfo.UseShellExecute = false;
    rsync.StartInfo.RedirectStandardInput = true;
    rsync.StartInfo.RedirectStandardOutput = true;
    rsync.StartInfo.RedirectStandardError = true;
    rsync.StartInfo.Arguments = String.Join(" ", new[] { "-rltzh --progress --chmod=a=rw,Da+x", FileUtils.EncodeParameterArgument(sourceFolder), FileUtils.EncodeParameterArgument(destFolder) });

    rsync.ErrorDataReceived += rsync_ErrorDataReceived;
    rsync.OutputDataReceived += rsync_OutputDataReceived;

    rsync.Start();
    BindToUiConrol(rsync.StandardInput);

    rsync.WaitForExit();

    return rsync.ExitCode;
}

private void rsync_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    //Magic!
}

private void rsync_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    //Even more Magic!
}

private void BindToUiConrol(StreamWriter standardInput)
{
   if(this.InvokeRequired)
   {
       this.BeginInvoke(new Action<StreamWriter>(BindToUiConrol), standardInput);
       return;
   }

   //Hook up events here so a single line text box dumps it's text in when you hit enter.
}

这就是我卡住的地方。如果我没有在同一行上不断更新的 %,我只会让它在新行进入时不断转储,但是我如何处理重新使用的行并放入新值?

我梦想的解决方案是在表单本身中嵌入一个控制台窗口,类似于HyperTerminal旧版本的窗口,但我不知道如何在 .NET 中做到这一点。


这是一个显示问题的示例程序

public class Program
{

    private static void Main(string[] args)
    {
        Console.Write("1");
        Console.WriteLine();

        Console.Write("2");
        Console.CursorLeft = 0;
        Console.Write("3");
        Console.WriteLine();

        Console.Write("4");
        Console.WriteLine();
    }
}

如何编写将显示的表单应用程序

1
3
4

在它运行进程之后的控件中。

4

2 回答 2

1

一般来说,这不是一个简单的问题。这与 Windows/Console 应用程序并没有真正写入标准输出和标准错误这一事实有关,它们写入“控制台”。当您一次只关心所有文本和所有错误文本时,有各种技巧和东西可以使标准输出和标准错误正常工作,但没有什么能很好地交互,因为缓冲的方式。

关注此讨论以获取更多信息:

用 C# 编写控制台包装器?

于 2013-08-23T23:18:30.980 回答
-1

您要做的是将终端文本附加到多行文本框或 RichTextBox。

您还需要捕获该控件上的键盘事件。

您可能会遇到的一个问题是程序输入和在不同线程上运行的 GUI。

如何从 C# 中的另一个线程更新 GUI 上的文本框

快速将文本附加到文本框

澄清原始问题后, 您要寻找的是检测回车的 '\r' 字符,然后您需要移回文本框内容中的最后一个 '\n' 换行符。

您可以通过多种方式做到这一点。

  1. 首先保留一个包含每一行的列表,然后删除最后一行。并将文本附加到上一行之后。

  2. 您可以使用Regex将文本框内容匹配到文本框中的最终换行符。我相信正则表达式是 "^.*\n" http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx

  3. 只需将文本框内容截断到String.LastIndexOf('\n') http://msdn.microsoft.com/en-us/library/system.string.lastindexof.aspx

编辑#2:

这个问题似乎是针对确定光标移动的触发器。
Microsoft 在以下链接中提供了参考:http: //msdn.microsoft.com/en-us/library/h21280bw.aspx

您使用 Console.Left = 0 给出的第二个示例似乎引发了异常。由于这是此解决方案的人为答案,我假设 oyu 真的只关心 rsync ,我冒险猜测它只使用'\r','\n''\b'. 唯一的另一个问题是它是否使用 ANSI 转义码http://en.wikipedia.org/wiki/ANSI_escape_code

最后一个循环必须读取输入并解析适当的字符。我会推荐一个 BackgroundWorker,因为 GUI 会阻止等待循环。

于 2013-08-23T20:49:06.403 回答