【问题标题】:How to send input to the console as if the user is typing?如何将输入发送到控制台,就好像用户正在打字一样?
【发布时间】:2010-10-01 20:41:11
【问题描述】:

这是我的问题。我有一个必须在 TTY 中运行的程序,cygwin 提供了这个 TTY。当我重定向 stdIn 时,程序失败,因为它没有 TTY。我不能修改这个程序,需要一些自动化的方法。

如何抓取 cmd.exe 窗口并向其发送数据并让它认为用户正在输入?

我正在使用 C#,我相信有一种方法可以使用 java.awt.Robot 来做到这一点,但由于其他原因我必须使用 C#。

【问题讨论】:

标签: .net automation cmd stdin


【解决方案1】:

我已经弄清楚如何将输入发送到控制台。我使用了 Jon Skeet 所说的。我不是 100% 确定这是实现这一点的正确方法。

如果有任何 cmets 可以使这变得更好,我很想来这里。我这样做只是为了看看我能不能弄明白。

这是我盯着的等待用户输入的程序

class Program
{
    static void Main(string[] args)
    {
        // This is needed to wait for the other process to wire up.
        System.Threading.Thread.Sleep(2000);

        Console.WriteLine("Enter Pharse: ");

        string pharse = Console.ReadLine();

        Console.WriteLine("The password is '{0}'", pharse);


        Console.WriteLine("Press any key to exit. . .");
        string lastLine = Console.ReadLine();

        Console.WriteLine("Last Line is: '{0}'", lastLine);
    }
}

这是控制台应用程序写入另一个应用程序

class Program
{
    static void Main(string[] args)
    {
        // Find the path of the Console to start
        string readFilePath = System.IO.Path.GetFullPath(@"..\..\..\ReadingConsole\bin\Debug\ReadingConsole.exe");

        ProcessStartInfo startInfo = new ProcessStartInfo(readFilePath);

        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardInput = true;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;

        Process readProcess = new Process();
        readProcess.StartInfo = startInfo;

        // This is the key to send data to the server that I found
        readProcess.OutputDataReceived += new DataReceivedEventHandler(readProcess_OutputDataReceived);

        // Start the process
        readProcess.Start();

        readProcess.BeginOutputReadLine();

        // Wait for other process to spin up
        System.Threading.Thread.Sleep(5000);

        // Send Hello World
        readProcess.StandardInput.WriteLine("Hello World");

        readProcess.StandardInput.WriteLine("Exit");

        readProcess.WaitForExit();
    }

    static void readProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        // Write what was sent in the event
        Console.WriteLine("Data Recieved at {1}: {0}", e.Data, DateTime.UtcNow.Ticks);
    }
}

【讨论】:

    【解决方案2】:

    这听起来像是SendKeys() 的任务。它不是 C#,而是 VBScript,但尽管如此 - 你要求 some 自动化它的方式:

    Set Shell = CreateObject("WScript.Shell")
    
    Shell.Run "cmd.exe /k title RemoteControlShell"
    WScript.Sleep 250
    
    Shell.AppActivate "RemoteControlShell"
    WScript.Sleep 250
    
    Shell.SendKeys "dir{ENTER}"
    

    【讨论】:

    • 我实际上已经在查看 SendKeys 了。 SendKey 是 .NET 2.0 框架的一部分,因此我可以从 C# 中使用它。我会看看这是否有效。
    • 使用 SendKeys 类基本上需要您激活 TTY - 然后您只需调用 SendKeys.Send 并发送击键。
    • 但是不行,偶尔会发一键,就这样。如果我不能尽快让它工作,我想我可能会问另一个关于 sendkey 的问题。
    • 好的,问题是我失去了注意力,现在已经解决了。
    • 另请参阅stackoverflow.com/questions/6838363/…,了解与 SendKeys 等效的 C++。当 Jon Skeet 说“激活”时,我相信他指的是“使应用程序的窗口成为焦点”的 AppActive。显然没有可靠的方法可以将消息发送到窗口stackoverflow.com/questions/1220820/…
    【解决方案3】:

    您能否在您的代码中启动程序(或 cygwin),使用 ProcessStartInfo.RedirectStandardInput(和输出/错误)来控制数据流?

    【讨论】:

    • 我可以从它开始。但是一旦达到程序必须拥有 TTY 的地步,它就会失败。该程序要求输入密码,并修改 TTY 以隐藏击键。它无法对重定向的流执行此操作,因此它失败了。
    【解决方案4】:

    我前段时间遇到过类似的问题,cygwin 应该写一些有用的信息(确切的 cygwin 函数、错误文本和 WINAPI 错误代码)到错误流,你应该把它重定向到某个地方并阅读它写的内容。

    【讨论】:

    • 不,cygwin 将 everything 写入 StandardErrorStream。该错误与 ioclt 不适合该设备有关,这意味着我需要一个真正的 TTY 才能使用它。
    • bash: [####: #] tcsetattr: 设备的 ioctl 不合适
    猜你喜欢
    • 2013-04-21
    • 2011-05-23
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2018-04-17
    • 2019-01-06
    相关资源
    最近更新 更多