在同步模式下运行Windows GUI应用程序?

问题描述:

我在Windows上调试GUI应用程序,我想找出谁是某些消息的发件人。在linux上,我可以在synchronized mode中运行应用程序,并在调用堆栈中查找发件人。 Windows中是否有等效模式?在同步模式下运行Windows GUI应用程序?

AFAIK没有内置的能力来做到这一点。

但我们先来调查一下这个问题。你想知道谁是消息的发件人。但是你应该知道,窗口消息处理可以通过以下指标分析可分为:

  1. 发布VS发邮件(PostMessage VS SendMessage)。
  2. 发送到属于另一个线程vs发送者线程的窗口的消息。
  3. 发布到某个线程(未绑定到特定窗口,因此未被窗口过程处理)的消息。

可在跟踪直接仅当该消息是发送(未贴)发送到一个窗口,而该呼叫到SendMessage(或类似的)中,以该窗口所属的线程发出。在这样的情况下,您会在调用堆栈中看到发件人。

如果消息是从另一个线程发送的 - 您将而不是在调用堆栈中看到它。只是因为调用堆栈只显示属于当前线程的调用链。当从另一个线程发送消息时,系统执行以下操作:

  1. 暂停调用者线程。
  2. 将此消息放入拥有该窗口的线程队列中。
  3. 当该线程调用GetMessage(或类似的) - 消息被分派到窗口。
  4. 最后操作系统恢复调用者线程。 SendMessage返回窗口过程返回的结果。

在这种情况下,您可能会尝试间接识别来电者。用断点中断程序,并尝试搜索挂起的线程,这些线程在致电SendMessage或类似程序时被阻止。

最后,发布的消息不可能通过上述方法进行跟踪。您可以尝试在对PostMessage的呼叫中添加条件断点,但如果呼叫者属于另一个问题 - 这将更加复杂。

valdo是正确的。调用SendMessage直接调用你的应用程序wndproc。对PostMessage的调用将消息发送到消息队列,然后您的应用程序通过消息泵(循环,getmessage,translatemessage,dispatchmessage)来接收消息。所以,就像他所说的,如果消息是通过SendMessage发送的,那么函数的被调用者将显示在调用堆栈中。如果它是通过PostMessage发送的,它不会。

+0

那么没有办法让PostMessage的行为像SendMessage?如果是这样,我看到的唯一方法是暂时用SendMessage替换所有PostMessage调用。 – ks1322 2011-05-31 09:31:23

+0

不,没有办法使Postmessage像sendmessage一样行事,post消息是异步的,并且将消息发送给消息队列,正如我所说的,发送消息直接绕过消息队列并直接调用应用程序wndproc。当你调用PostMessage时,它会立即返回,但在调用线程上发送消息块,因为它通过调用传递给它的hwnd的wndproc来访问wndproc。 – johnathon 2011-05-31 09:39:46

+0

对于单线程的情况,这个答案是正确的。 'SendMessage'在不同的线程中工作方式不同,因为您必须在其线程上调用窗口的WindowProc,而不是您自己的。由于每个线程都有自己的调用堆栈,因此您的SendMessage调用将不会与WndProc调用位于同一个堆栈中。 – MSalters 2011-05-31 12:03:40