关于linux:Interactive c#System.Process not Echoing input

Interactive c# System.Process not Echoing input

鉴于以下代码在Linux上的Mono中运行,我可以从C成功运行ssh,并在远程设备上获得shell提示。我可以输入命令并获得输出。然而,我不知道如何把我输入的内容输入到那个shell中进行回音。当我输入ls并点击Enter时,你看不到ls或按Enter键时的换行符,你只看到它的输出。我已经确认ssh正在分配tty。目标shell是交互模式下的bash,因此在那里启用了readline。问题必须在于C_是如何将stdin和stdout连接到Console的。谷歌没有帮助,所以我希望这里有人能帮上忙。

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
P></

我会让它的读者兴趣to convert this to the # to c f #队列。这是基本的bool System.ConsoleDriver.SetEcho(bool enable)简单的反射。P></

现在用下面的伪代码:P></


setEcho(true)
var p = startProcess ()
p.WaitForExit()
setEcho(false)
P></


也许这就是我想给你: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());
        }
    }
}

first example of using tab while typing a dircheck ttyexample of echoing the ssh commmandsP></

编辑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输入,局部。如果它不只是Console.writeLine(inputText)add to the环,和做。P></

如果你想更好的控制阅读和写作,字节明智的考虑。只是-随你便,表和其他控制characters might not be easy to handle that。P></

如果你真的需要这些为好,而不是使用ReadKey(通)和控制在任何你需要的特点。你记得集Console.TreatControlCAsInput = true;or to to send会不会是没有你温柔的CMD + cAT的应用。P></

哦,但鱼的调控序列(ALT键与CMD或从Windows modifier)出现在学院?呃……我想我是真的进入一个学院。System.Window.Formsthat is part of how to我没有线索,以及复制行为与# of C在Windows。P></

As for the other,and probably多easier option:我不invoke the executable裸体的SSH。而不是运行SSH和开放壳内of that thing。"-c 'ssh -ttt hostname'"/usr/bin/bash布尔。我知道你的问题是emulation tty,just let the handle that for You壳。虽然我Console.TreatControlCAsInput = true;applies,至少如果你想好能to THROUGH Ctrl + C as a命令序列。P></