【问题标题】:.NET call to send [enter] keystroke into the current process, which is a console app?.NET 调用将 [enter] 击键发送到当前进程,这是一个控制台应用程序?
【发布时间】:2012-02-19 10:14:12
【问题描述】:

有没有办法将 [enter] 击键插入当前进程,强制 Console.ReadLine() 上的线程阻塞退出?

更多信息(可以忽略)

我有一个 C# 控制台应用程序,它正在运行另一个在 Console.ReadLine() 上阻塞的线程。由于 Console.ReadLine 调用了一个在 Windows 内部非托管代码深处运行的本机 Windows 线程,它在解除阻塞之前不会中止,并且在它收到键盘上的按键之前不会中止。

因此,当我在这个线程上调用“.Abort”时,在 C# .NET 中,直到我在控制台上手动按 [enter] 才会出现。我想自动化这个按键。

【问题讨论】:

    标签: c# .net visual-studio


    【解决方案1】:

    使用 PostMessage 发送 [enter] 进入当前进程:

    class Program
    {
        [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
        private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
    
        const int VK_RETURN = 0x0D;
        const int WM_KEYDOWN = 0x100;
    
        static void Main(string[] args)
        {
            Console.Write("Switch focus to another window now to verify this works in a background process.\n");
    
            ThreadPool.QueueUserWorkItem((o) =>
            {
                Thread.Sleep(4000);
    
                var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
                PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
            });
    
            Console.ReadLine();
    
            Console.Write("ReadLine() successfully aborted by background thread.\n");
            Console.Write("[any key to exit]");
            Console.ReadKey();
        }
    }
    

    这个答案也解决了这样一个事实,即在 ReadLine() 上调用 .Abort 在 C# 中不起作用,因为 ReadLine() 在 Windows 内核深处的非托管代码中运行。

    此答案优于任何仅在当前进程具有焦点时才有效的答案,例如SendKeysInput Simulator

    【讨论】:

    • 这适用于 winRT 吗?有人有更新吗?
    • 您也可以将其与[DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow() 结合使用以将返回发送到附加的控制台,即使您的进程是从父进程运行并且没有自己的窗口。
    【解决方案2】:

    http://inputsimulator.codeplex.com/ 在控制台应用程序中非常出色,只要当前控制台应用程序具有焦点即可。

    演示代码:

    InputSimulator.SimulateKeyPress(VirtualKeyCode.RETURN);
    Console.Write("[enter] is now queued in the buffer for this console app.\n");
    Console.ReadLine();
    Console.Write("Program go to here, without the user pressing [enter] on the keyboard.\n");
    Console.Write("[any key to exit]\n");
    Console.ReadKey();
    

    除非当前控制台应用程序没有焦点,否则此代码不起作用,如果所述控制台进程被设计为在后台运行,则会导致键被插入其他 3rd 方应用程序的各种问题。

    另请参阅对Interrupt Console.ReadLine 的答复,以及涉及使用 PostMessage 的新接受答复。

    【讨论】:

      【解决方案3】:

      好吧,您总是可以使用 System.Windows.Forms.SendKeys.SendWait(string keyStrokes) 来注入 Enter 击键 - 这显然需要引用 System.Windows.Forms。

      但是,我倾向于质疑我的架构,也许会使用适当的线程等待机制。有几种方法可以实现这一点 - 这是我以前在这方面提供帮助的一篇文章: http://www.albahari.com/threading/part2.aspx

      干杯, 克里斯。

      【讨论】:

      • 谢谢,但是 SendKeys 仅适用于 Windows 窗体应用程序,它要求当前应用程序位于前台。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-15
      相关资源
      最近更新 更多