我有一个在库中使用键盘挂钩程序的应用程序。一条消息的钩子中的 wParam 是 255,我们认为它是“(保留 / OEMClear)”。我想弄清楚这条消息的来源,因为它会导致我的应用程序在库中崩溃,并且鉴于它不应该发生,最好识别它。该消息仅在我们拥有的一台 PC 上重复出现 - 其他计算机根本看不到该消息。
那么,有没有办法追踪发送到窗口的消息的来源,或者系统上的所有消息?
我有一个在库中使用键盘挂钩程序的应用程序。一条消息的钩子中的 wParam 是 255,我们认为它是“(保留 / OEMClear)”。我想弄清楚这条消息的来源,因为它会导致我的应用程序在库中崩溃,并且鉴于它不应该发生,最好识别它。该消息仅在我们拥有的一台 PC 上重复出现 - 其他计算机根本看不到该消息。
那么,有没有办法追踪发送到窗口的消息的来源,或者系统上的所有消息?
没有内置方法可以找出谁发送了窗口消息,甚至 win32k 也没有跟踪这一点;您也许可以使用内核调试器和条件断点找到它。
但是,我认为您并不真的需要这些信息。您需要使您的应用程序正确处理发送给它的任何消息。
(我最初建议使用 Spy++ 或 winspector,但它们不会与消息的发送挂钩。这甚至没有意义!窗口接收消息但他们不发送消息,线程会这样做。我会离开我的关于使用调试器的建议。)
有时调试会有所帮助。尝试下载 Windows PDB文件并设置一个断点,该断点仅在出现这些消息之一时才命中。在这一点上查看调用堆栈通常可以对事情发生的原因有所了解。发布的消息和从其他进程发送的消息将挫败这种方法。
我想出了一种技术,用于确定谁在一次性调试/故障排除会话期间跨线程/进程发送 win32 窗口消息。它需要做出几个假设,所以它不是 100% 可靠的,但到目前为止我还没有发现它不起作用的情况。
基本思想是利用这样一个事实,即当消息到达时,接收窗口线程通常被阻塞在其消息循环中等待GetMessage()
(特别是, )。当消息被传递时,发送线程准备接收线程,将其拉出等待状态。
事实证明,Windows 提供了使用Windows 事件跟踪来精确跟踪哪些线程正在准备哪些其他线程的方法。使用这个特性,通常可以确定哪个线程发送了消息——它是准备接收线程的线程。甚至可以看到发送线程在发送消息时的调用堆栈是什么,甚至可以看到堆栈的内核端 ( win32k
) 部分!
基本程序是这样的:
GetMessage
。例如,在下面的屏幕截图中,TID 7640 接收到来自 WindowsTerminal.exe、TID 1104的外壳挂钩消息:
我不确定这是否符合您的要求,但请查看 sysinternals 的 Process Monitor。
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
它显示了进程发生的所有事情,所以我假设它也捕获消息。该网站在撰写本文时已关闭,因此我无法检查。