找到可能的解决方案!
我相信我已经找到了解决办法!我将继续测试以确保它确实有效,但我充满希望:) 我已经详细说明了如何在编辑问题三中找到解决方案!
对于任何希望了解我的问题背后的完整背景以及我从这个问题的输入中尝试过的内容的人,请参阅: 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(新 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 次,程序不会再次崩溃。然后我试图让它崩溃两次。也没有时间,
我发现等待大约 5 秒似乎增加了我的几率:我触发消息的表单仍然是焦点(顶部栏将是蓝色),就在我按下冻结按钮之后,然后 msgbox 会弹出,与顶部也是蓝色的(我认为是焦点),它们都仍然“焦点”(至少是蓝色的哈哈)。然后大约 5 秒后,原始表格会失去焦点,看到之后,我会尝试点击确定。
我目前在想,等待一段时间然后确认消息框有时会使我的程序不会崩溃,因为它正在使消息超时,因此它不会返回。我不知道为什么返回的消息会影响我的程序实际执行的操作。这是澄清会有所帮助的领域:)
编辑三:
所以我在 Winspector 中寻找更多,我发现如果我等待 WM_ERASEBKGND 出现在我的桌面窗口中(这是在 Winspector 中标记为“sysListView32 'FolderView'”的窗口),然后在我的 msgbox 上点击“OK” ,那么程序就不会崩溃了,有意思!通常需要接近超时时间才能显示 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
到目前为止,我也注意到这对常规应用程序的使用没有不利影响!这是有道理的,因为我认为我的程序中没有故意涉及任何用户定义的消息。
在确保我的解决方案没有问题并且运行良好之前,我将把这个问题留得更久一些。感谢那些在调试的中间阶段给我一些建议的人:)