【发布时间】:2012-01-25 02:37:54
【问题描述】:
找到了可能的解决方案!
我相信我已经找到了解决办法!我将继续测试以确保它确实有效,但我充满希望:) 我已经详细说明了我是如何在编辑问题三中找到解决方案的!
对于任何希望了解我的问题背后的完整背景以及我根据此问题的输入尝试过的内容的人,请参阅:http://pastebin.com/nTrEAkVj
随着我的研究和情况的进展,我将经常编辑此内容(大多数工作日每天 > 3 次),所以如果您对我的问题感兴趣或对我的问题有一些信息或知识,请继续查看:)
快速背景:
我制作的这个应用程序可以通过更改我的屏幕保护程序或锁定我的工作站来崩溃,并且通常只要向它发送 WM_WININICHANGE/WM_SETTINGSCHANGE 消息。
如果我可以通过更改屏幕保护程序来持续使我的应用程序崩溃,那么这样做的一部分就是向我的应用程序发送某种消息(不一定是 Windows 消息,我的意思是最一般意义上的消息),这反过来是对我的应用程序来说是灾难性的。因此,我试图找到一种方法来阻止导致我的问题的任何消息被我的应用程序处理。我知道这不是解决问题的最佳方法,因此您无需告诉我。查看背景信息或询问为什么这让您感到困扰(有充分的理由)。
我的问题:
有几件事可以帮助我解决我的问题,根据相关性标记(1 最相关,3 稍微不太有用):
-
我正在尝试使用 Wndproc() 过滤掉我的消息,如下所示:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) If CInt(m.Msg) <> CInt(26) then MyBase.WndProc(m) end if End Sub但是,根据 Windspector 的说法,WM_WININICHANGE 消息仍在发送到我的应用程序(这是有道理的),但它也被返回为 0...如果它工作正常,则不应该发生这种情况,它应该不返回任何东西,不是吗?关于为什么它没有按我预期的那样工作以及如何使它工作的信息将非常有帮助!
-
我也尝试过使用消息过滤器:
Public Class MyMessageFilter Implements IMessageFilter Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage ' Return true for messages that you want to stop << someone elses comment Return m.Msg = 26 End Function End Class然后添加到我的 mybase.load 处理方法:
Application.AddMessageFilter(New MyMessageFilter())
但是它们似乎只过滤某些消息,而像我这样的消息显然没有被捕获。关于是否绝对不可能使用任何类型的过滤器来捕获 WM_ 消息或是否有可能使用消息过滤器来实现我的目标的其他方法的信息也会有所帮助。
我可以通过哪些其他方式(除了我发现的带有 message.msg = WM_WININICHANGE = 26 的一条 Windows 消息)更改我的屏幕保护程序向我的应用程序发送任何类型的消息?更改屏幕保护程序的另一种消息是否也可能是致命的?
如果还有其他关于我的情况可能有用的信息,请告诉我,我会尽我所能!提前感谢您提供的任何帮助:)
编辑:
如果我只发送 WM_CHANGESETTING 消息,并让我的程序等待我发送消息的 sendmessagetimeout 的超时长度,那么我的程序不会崩溃......看起来响应是我的崩溃节目……有趣。我绝对接近我的解决方案!我正在考虑进行更多测试,以便找出一种方法来确保我的程序不会响应该消息。
编辑二:
我今天发现了一些非常有前途的东西:我完全像这样定义了我的 wndproc 函数:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If CInt(m.Msg) <> CInt(26) Then
MyBase.WndProc(m)
Else
MessageBox.Show("Get to work!", "Attention", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification)
End If
End Sub
然后我尝试运行我的程序,然后使用以下命令发送 WM_SETTINGCHANGE 消息:
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, IntPtr.Zero, _
SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, IntPtr.Zero)
在我制作的另一个程序中。那你问怎么了?好吧,我尝试了几次,每次都会弹出消息框(我为它选择的词是微不足道的),然后我尝试等待不同的时间,然后按确定,然后我会看到我的主窗体发生了什么。很多时候,没有什么不同,它仍然会崩溃。但偶尔,可能是 1/5 次,程序仍然会在之后重新发送!然后,如果确实如此,我会尝试再次发送消息,然后再一次,通常他们会在程序的同一运行期间第二次失败,但偶尔会再次失败,大约是另外 1/5 次,程序不会再次崩溃。然后我试图让它崩溃两次。而且它也没有,无论我尝试发送消息多少次,无论我在 msgbox 弹出后等待了多长时间,它几乎总是不会崩溃。
我发现等待大约 5 秒似乎增加了我的几率:我触发消息的表单仍然是焦点(顶部栏将是蓝色),就在我按下冻结按钮之后,然后 msgbox 会弹出向上,顶部也是蓝色的(我假设是焦点),它们都仍然“焦点”(至少是蓝色的哈哈)。然后大约 5 秒后,原始表单会失去焦点,看到之后,我会尝试点击 ok。
我目前认为,等待一段时间然后确认消息框有时会使我的程序不会崩溃,因为它正在超时消息所以它不会返回。我不知道为什么返回的消息会影响我的程序实际执行的操作。这是澄清会有所帮助的领域:)
编辑三:
所以我在 Winspector 中寻找更多信息,我发现如果我等待 WM_ERASEBKGND 出现在我的桌面窗口(在 Winspector 中标记为“sysListView32 'FolderView'”的窗口)中,然后点击“OK”在我的msgbox上,那么程序就不会崩溃了,有趣!通常需要接近超时时间才能显示 WM_ERASEBKGND 消息的 sendmessagetimeout。这当然是在我的自制测试应用程序发送 WM_SETTINGCHANGE 消息之后。
所以,在这之后,我决定多看看 Winspector,因为也许我可以找到更多有用的队列?由于显然等待 winspector 显示消息已发送到我的桌面,因此对于我的程序来说根本不是真正的修复。我在我的程序进程下发现了一些异常命名的窗口:一个名为“.NET -BroadcastEventWindow.2.0.0.0.378734a.0”,另一个名为“GDI+ Hook Window Class 'GDI+ Window'”,带有一个名为“IME”的子窗口默认输入法'"。
我决定查看进入这些窗口的消息,看看它们是否接收到任何可识别的消息,例如 WM_SETTINGCHANGE 或 WM_ERASEBKGND。事实证明,他们不经常收到消息:我认为 GDI+ 没有收到任何消息,但 .NET -BroadcastEventWindow 收到了一些消息。当我单击我的应用程序窗口或之后的另一个窗口时,进入 BroadcastEventWindow 的大多数只是 WM_appactivate。
但是...我注意到 .Net BroadcastEventWindow 收到了我的 WM_CHANGESETTING 消息!!!!我查看显示的其他消息:不是很多,但我注意到当应用程序因错误而崩溃时,有一条我不认识的消息:WM_USER+7194 (0x201A)。嗯,让我们看看那是什么。在我用谷歌搜索之后,我发现它似乎是一个应用程序/用户定义的消息,然后在再次搜索与之相关的问题之后,我注意到有人能够使用过滤器来过滤掉这个消息并解决一个问题他们的(http://www.pcreview.co.uk/forums/handling-wm_user-messages-t1315625.html)。至少对我来说值得一试吧?所以我重新添加了我之前尝试过的过滤器,并更改了要过滤的值。应用程序没有崩溃!!!!!!!
接下来我尝试让我的工作站锁定以查看它是否仍然崩溃(因为以前只是向它发送单独的 WM_CHANGESETTING 消息)。事实证明,它仍然崩溃了 :( 但是,我在 winspector 中再次查看了那个窗口,哦,嗯,两条新的 WM_USER 消息:WM_USER+7294(0x207E) 和 WM_USER+7189(0x2015)。所以我尝试将它们过滤掉太...然后它也不会在工作站锁定时崩溃!!!:D
到目前为止,我也没有注意到这对常规应用程序的使用有任何不利影响!这是有道理的,因为我认为我的程序中没有故意涉及任何用户定义的消息。
在我确定我的解决方案没有问题并且运行良好之前,我会将问题留待更长时间。感谢那些在调试的中间阶段给我一些建议的人:)
【问题讨论】:
-
无论如何我可以得到我在另一个问题中输入的信息? (因为我认为你也是,这是我需要以某种方式包含的相关信息)
-
查看我对问题的最后一次编辑,了解我是如何解决问题的。尽管 Olivier Jacot-Descombes 的想法是解决方案的一部分,但我没有将其标记为答案,因为它非常缺乏解决方案的关键细节以及如何以在这种情况下有用的方式实际实施它。跨度>
标签: .net vb.net multithreading messages windows-messages