【问题标题】:How to enter input into an application running through a CMD Process in C#?如何在 C# 中通过 CMD 进程运行的应用程序输入输入?
【发布时间】:2014-01-08 09:49:20
【问题描述】:

我正在尝试这样做:

        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("git config --global user.name \"My Name\"");
                sw.WriteLine("git config --global user.email \"my email\"");
                sw.WriteLine("call start-ssh-agent");
                sw.WriteLine("ssh-add c:\\temp\\ServerPull.ppk");
                System.Threading.Thread.Sleep(10000);
                sw.WriteLine(Environment.NewLine);
                sw.WriteLine("git clone git@github.com:myrepo");
            }
        }

        Console.WriteLine("Done");
    }

问题是“ssh-add”命令需要输入密码,而我不能让 C# 输入它。 Thread.Sleep 之后的任何其他命令都会进入缓冲区,直到我自己在 CMD 框中实际输入内容。

Console.Writeline() 输出到同一个框,但实际上并没有被“输入”

编辑: 为清楚起见,我不打算执行 Console.ReadLine() 或实际获取用户的输入。这些命令是我需要它们的方式,但我需要自动将字符串发送到另一个要求输入密码的应用程序(ssh-add)。通过 sw.WriteLine 编写密码短语不起作用,因为控制台在等待输入时不会执行任何代码。

编辑: 在编写我的第一个编辑时,我对来自 cmets 的一些代码建议产生了灵感。现在结束了:

    const int VK_RETURN = 0x0D;
    const int WM_KEYDOWN = 0x100;

    static void Main(string[] args)
    {
        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("git config --global user.name \"my name\"");
                sw.WriteLine("git config --global user.email \"my email\"");
                sw.WriteLine("call start-ssh-agent");

                var enterThread = new Thread(
                    new ThreadStart(
                        () =>
                        {
                            Thread.Sleep(10000);
                            var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
                            PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
                        }
                        ));

                enterThread.Start();
                sw.WriteLine("ssh-add c:\\temp\\ServerPull.ppk");
                sw.WriteLine("git clone myrepo");
                sw.WriteLine("ping 127.0.0.1");
            }
        }

        Console.WriteLine("Done");
    }

    [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
    private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

延迟后发送回车键。我应该能够从那里修改它以发送我需要的任何东西。

【问题讨论】:

    标签: c# git cmd


    【解决方案1】:

    我认为你可以使用 args[] 的 main 方法。请参阅下面的示例。

    public class CommandLine
    
    {
    
    public static void Main(string[] args)
    
    {
    
    Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;
    
        p.StartInfo = info;
        p.Start();
    
        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine(string.Format("git config --global user.name {0}",args[0]));
                sw.WriteLine(string.Format("git config --global user.email {0}",args[1]));
                sw.WriteLine("call start-ssh-agent");
                sw.WriteLine(string.Format("ssh-add {0}",args[2]));  
                System.Threading.Thread.Sleep(10000);
                sw.WriteLine(Environment.NewLine);
                sw.WriteLine("git clone git@github.com:myrepo");
            }
        }
    
        Console.WriteLine("Done");
    }}
    

    执行您的 exe 并在命令行中使用参数:

    x:\> yourapp.exe user2645643 xyx@yourdomain.com c:\temp\ServerPull.ppk

    更新

    那么它就很简单了。使用var inp = Console.ReadLine() 并将输入变量放置在您想要的任何位置。

    【讨论】:

    • 问题不在于输入参数,而是 ssh-add 需要来自 Console.ReadLine() 之类的输入。例如,它就在那里等着我按 Enter,所以我需要以某种方式按 Enter。转到 CMD 的实际命令很好。
    【解决方案2】:

    这适用于键入命令提示符

            foreach (var v in message)
            {
                PostMessage(cmdProcess.MainWindowHandle, WM_CHAR, (IntPtr)v, IntPtr.Zero);
            }
    
            PostMessage(cmdProcess.MainWindowHandle, WmKeyUp, (IntPtr)Keys.Enter, IntPtr.Zero);
    

    【讨论】:

      【解决方案3】:

      我认为你可以做到这一点,..

      https://stackoverflow.com/a/9634490/3156689

      此链接解释了如何将返回键发送到控制台。它比模拟按键或关闭标准输入流更好

      【讨论】:

      • 获得相同的行为。使用相同的代码并尝试设置 var hWnd = p.MainWindowHandle;
      • 最后根据这个想出来的。通过相关更改更新了问题。
      猜你喜欢
      • 2014-03-03
      • 1970-01-01
      • 2016-08-11
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多