如何在不挂起控制台应用程序的情况下从工作线程调用Windows PostMessage函数?

时间:2017-08-04 01:32:04

标签: c# multithreading visual-studio pinvoke

在代码中重新创建了问题:

class Program
{
    private const int VK_ESCAPE = 0x1B;
    private const int WM_KEYDOWN = 0x0100;

    [DllImport("User32.dll")]
    private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    static void Main(string[] args)
    {
        Task.Run(() =>
        {
            var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
            bool hasSucceeded = PostMessage(hWnd, WM_KEYDOWN, VK_ESCAPE, 0);
            return;
        });

        Console.WriteLine("PostMessage works as expected in Debug >> Start Debugging mode.");
        if ((Console.ReadKey()).Key == ConsoleKey.Escape)
        return;
    }
}

我正在尝试通过从工作线程调用Console.ReadKey()取消PostMessage。这在我运行Debug>>下的代码时有效。启动调试模式。

但是,当我在Debug>>下运行代码时它启动没有调试模式挂起?任何回复/解决方案都非常感谢。

1 个答案:

答案 0 :(得分:3)

Raymond Chen撰写了一篇名为"You can't simulate keyboard input with PostMessage"的好文章。在继续您的方法之前,您可能希望对此进行审核。

话虽如此,但直接的问题可能是您必须使用GetConsoleWindow函数(来自Kernel32.dll)来获取自己的控制台窗口的句柄。因为,正如其他人已经评论过的那样,您的流程并不真正拥有该窗口(它属于关联的conhost.exe流程)。

鉴于此,以下代码“有效”:

class Program
{
    private const int VK_ESCAPE = 0x1B;
    private const int WM_KEYDOWN = 0x0100;

    [DllImport("User32.dll")]
    private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetConsoleWindow();

    static void Main(string[] args)
    {
        Task.Run(() =>
        {
            bool hasSucceeded = PostMessage(GetConsoleWindow(), WM_KEYDOWN, VK_ESCAPE, 0);
            return;
        });

        Console.WriteLine("PostMessage works as expected in Debug >> Start Debugging mode.");
        if ((Console.ReadKey()).Key == ConsoleKey.Escape)
            return;
    }
}

但是,这种方法可能不是实现你想要的正确方法(正如你所说的那样取消Console.ReadKey。)

有关使用超时的方法,请参阅this