Interactive c# System.Process not Echoing input
鉴于以下代码在Linux上的Mono中运行,我可以从C成功运行ssh,并在远程设备上获得shell提示。我可以输入命令并获得输出。然而,我不知道如何把我输入的内容输入到那个shell中进行回音。当我输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var process_info = new ProcessStartInfo("/usr/bin/ssh"); process_info.Arguments = "-ttt hostname"; Console.Out.WriteLine("Arguments: [" + process_info.Arguments +"]"); process_info.CreateNoWindow = true; process_info.UseShellExecute = true; var process = new Process(); process.StartInfo = process_info; try { process.Start(); process.WaitForExit(); exitCode = process.ExitCode; } catch (Exception e) { exitCode = this.ExitCode == 0 ? 255 : exitCode; Console.WriteLine(e.ToString()); } Console.Out.WriteLine("ExitCode:" + exitCode); |
河畔的stumbled and the of the same问题分析user4569980 helped很多。P></
This is the root of行为的原因,功能性单disables that the used of the currently tty的回声。see http:/ / / / www.linusakesson.net编程tty和HTTPS:/ / / / /单单github.com BLOB /硕士/ / / /系统级corlib STM / terminfodriver.cs # l204P></
解决方案:下面我P></
// mono sets echo off for some reason, therefore interactive mode
// doesn't work as expected this enables this tty feature which
// makes the interactive mode work as expected
let private setEcho (b:bool) =
// See https://github.com/mono/mono/blob/master/mcs/class/corlib/System/ConsoleDriver.cs#L289
let t = System.Type.GetType("System.ConsoleDriver")
if Env.isMono then
let flags = System.Reflection.BindingFlags.Static ||| System.Reflection.BindingFlags.NonPublic
if isNull t then
eprintfn"Expected to find System.ConsoleDriver.SetEcho"
false
else
let setEchoMethod = t.GetMethod("SetEcho", flags)
if isNull setEchoMethod then
eprintfn"Expected to find System.ConsoleDriver.SetEcho"
false
else
setEchoMethod.Invoke(null, [| b :> obj |]) :?> bool
else false
我会让它的读者兴趣to convert this to the # to c f #队列。这是基本的
现在用下面的伪代码:P></
setEcho(true)
var p = startProcess ()
p.WaitForExit()
setEcho(false)
也许这就是我想给你:P></
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | using System; using System.Diagnostics; using System.IO; using System.Threading; namespace Echo { class Program { private static void Read(StreamReader reader) { new Thread(() => { while (true) { int current; while ((current = reader.Read()) >= 0) Console.Write((char)current); } }).Start(); } static void Main(string[] args) { ProcessStartInfo startInfo = new ProcessStartInfo(@"/usr/bin/ssh"); startInfo.Arguments ="-ttty localhost"; startInfo.CreateNoWindow = true; startInfo.ErrorDialog = false; startInfo.RedirectStandardError = true; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; Process process = new Process(); process.StartInfo = startInfo; process.Start(); Thread.Sleep(15000); //time to login Read(process.StandardOutput); Read(process.StandardError); process.StandardInput.WriteLine("echoing your input now"); while (!process.HasExited) try { process.StandardInput.WriteLine(Console.ReadLine()); } catch {} Console.WriteLine(process.ExitCode.ToString()); } } } |
编辑1P></
You need重定向以回波standardinput恩,but then the Windows将它编写CMD模式(甚至在线在线(如果你使用console.readkey)=> process.standardinput.write),我知道你不能支持壳(while typing look at this的问题/答案如果你想挖到)。但单从Windows与Linux的SSH behaves differently CMD,下面是我acceptable:…即使是echoed commands and the while typing在目录管理表(看我的屏幕捕捉is below)!最后请注意that the tty是正确设置。P></
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading; namespace Echo { class Program { private static Process process; private static void Read(StreamReader reader) { new Thread(() => { while (!process.HasExited) { int current; while ((current = reader.Read()) >= 0) Console.Write((char)current); } }).Start(); } static void Main(string[] args) { ProcessStartInfo startInfo = new ProcessStartInfo(@"/usr/bin/ssh"); startInfo.Arguments ="-ttty localhost"; startInfo.CreateNoWindow = true; startInfo.ErrorDialog = false; startInfo.RedirectStandardError = true; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; process = new Process(); process.StartInfo = startInfo; process.Start(); Thread.Sleep(15000); //time to login Read(process.StandardOutput); Read(process.StandardError); process.StandardInput.WriteLine("echo echoing your input now"); //Console.ReadLine(); string theLine =" "; while (!process.HasExited) try { ConsoleKeyInfo kinfo = Console.ReadKey(true); char theKey = kinfo.KeyChar; theLine += theKey; process.StandardInput.Write(theKey) ; process.StandardInput.Flush(); if (theKey.Equals(' ')) { Console.WriteLine(theLine); theLine =" "; } } catch { } Console.WriteLine(process.ExitCode.ToString()); } } } |
P></
编辑2P></
如果你想管理终端序列也uparrow Escape the for the / downarrow,here is the队列(在线测试我的Ubuntu的终端)P></
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | string theLine =" "; string theEsc = ((char)27).ToString(); while (!process.HasExited) try { //byte[] bytes = new byte[1]; ConsoleKeyInfo kinfo = Console.ReadKey(true); char theKey = kinfo.KeyChar; theLine += theKey; switch (kinfo.Key) { case ConsoleKey.DownArrow: process.StandardInput.Write(theEsc+"[B"); break; case ConsoleKey.UpArrow: process.StandardInput.Write(theEsc+"[A"); break; default: process.StandardInput.Write(theKey); break; } process.StandardInput.Flush(); if (theKey.Equals(' ')) { Console.Write(theLine); theLine =" "; } } |
编辑3P></
只是我的意见的后续行动与恢复(参考回波suggested command to here)。This is the change to the队列:P></
1 2 3 | process.StandardInput.WriteLine("stty -a"); process.StandardInput.WriteLine("stty echo"); // or"reset" insted of"stty echo" process.StandardInput.WriteLine("echo echoing your input now"); |
回到你原来的队列(因为你不redirecting AISI标准输入),你可以给something like the followingP></
1 | process_info.Arguments = "-ttt hostname 'stty echo; '$SHELL' -i'"; // or reset insted of stty echo |
look at this答案太。P></
结论:在你的表现和更多的开源系统专门开发的C # is not to。过程做什么(除非一个回波intentionally redirects as the标准I/O做在这里,我在我的第一个实例和编辑1 &;2)。在行为echoing is of the Linux AS AS阱壳,在Windows:在As shown that can be管理编辑3。P></
msdn.microsoft.com HTTPS:/ / / /图书馆/德德system.diagnostics.processstartinfo.redirectstandardinput=28V 29.aspx vs.110 % %P></
只是捕捉和复制标准输入。P></
1 2 3 4 5 6 7 | process.Start(); StreamWriter processInputStream = process.StandardInput; do { String inputText = Console.ReadLine(): processInputStream.write(inputText); while(!process.HasExited) process.WaitForExit(); |
现在capturing process is the SSH周你不知道should be displayed EN输入,局部。如果它不只是
如果你想更好的控制阅读和写作,字节明智的考虑。只是-随你便,表和其他控制characters might not be easy to handle that。P></
如果你真的需要这些为好,而不是使用ReadKey(通)和控制在任何你需要的特点。你记得集
哦,但鱼的调控序列(ALT键与CMD或从Windows modifier)出现在学院?呃……我想我是真的进入一个学院。
As for the other,and probably多easier option:我不invoke the executable裸体的SSH。而不是运行SSH和开放壳内of that thing。