我正在我的应用内发布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
在旧版本的Windows中所做的,但我不知道在.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();
}
}
如何编写将显示
的Forms应用程序1 3 4运行过程后,在控件中
。
答案 0 :(得分:1)
一般来说,这不是一个微不足道的问题。这与Windows / Console应用程序没有真正写入标准输出和标准错误这一事实有关,它们写入“控制台”。当您只关心所有文本和所有错误文本时,有各种各样的黑客和标准错误可以正常工作,但没有什么能够以交互方式正常工作,因为事物被缓冲了。
请按照此讨论获取更多信息:
答案 1 :(得分:-1)
您要做的是将终端文本附加到多行文本框或RichTextBox。
您还需要捕获该控件上的键盘事件。
您可能遇到的一个问题是程序输入和GUI在不同的线程上运行。
How to update textbox on GUI from another thread in C#
原始问题澄清后 你要找的是检测回车的'\ r'字符,然后你需要回到文本框内容中的最后一个'\ n'换行符。
你可以通过多种方式做到这一点。
首先保留一个包含每一行的List,然后删除最后一行。并将文字附加在上一行之后。
您可以使用与文本框内容相匹配的Regex
与文本框中的最终换行符。我相信正则表达式会"^.*\n"
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx
只需将文本框内容截断为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将阻止等待循环。