[英]How can I call the windows PostMessage function from a worker thread without hanging the console application?
The issue recreated in code: 在代码中重新创建了该问题:
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;
}
}
I'm trying to cancel Console.ReadKey()
by calling PostMessage
from a worker thread. 我试图通过从辅助线程调用PostMessage
来取消Console.ReadKey()
。 This works when I run the code under Debug >> Start Debugging mode. 当我在“调试” >>“开始调试”模式下运行代码时,此方法有效。
However, when I run the code under Debug >> Start Without Debugging mode it hangs? 但是,当我在Debug >> Start Without Debugging模式下运行代码时,是否挂起? Any responses/solutions are greatly appreciated. 任何答复/解决方案,我们将不胜感激。
Raymond Chen has written a nice blog post titled "You can't simulate keyboard input with PostMessage" . Raymond Chen撰写了一篇不错的博客文章,标题为“您无法使用PostMessage模拟键盘输入” 。 You may want to review this, before continuing with your approach. 在继续您的方法之前,您可能需要检查一下。
Having that said, the immediate issue may be that you must use the GetConsoleWindow
function (from Kernel32.dll) to get a handle to your own console window. 话虽如此,当前的问题可能是您必须使用GetConsoleWindow
函数(来自Kernel32.dll)来获取自己的控制台窗口的句柄。 Because, as other have already commented, your process does not really own the window (it belongs to the associated conhost.exe
process). 因为,正如其他人已经评论过的那样,您的进程并不真正拥有该窗口(它属于关联的conhost.exe
进程)。
Given that, the following code sort of "works": 鉴于此,以下代码将“起作用”:
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;
}
}
But then, this approach is probably not the right approach to achieve what you want (cancelling a Console.ReadKey
, as you state). 但是,这种方法可能不是实现所需目标的正确方法(如您声明的那样取消Console.ReadKey
)。
See this for a way to use a timeout instead. 请参阅此以获取使用超时的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.