我怎样才能阻止我的应用程序从recieving一定"消息"?
可能的解决方案找到了!
我相信我已经找到了解决办法!我将继续测试,以确保它在事实上的工作,但我希望:)我有详细的我是如何找到解决方案在编辑的问题三个!
I believe I have found a solution! I will be continuing testing to make sure it DOES in fact work, but I'm hopeful :) I have detailed how I found the solution in EDIT THREE of the question!
有关任何人都希望知道我背后的问题,什么样的我试图从这个问题投入的结果的完整背景,看到这样的: HTTP ://pastebin.com/nTrEAkVj
For anyone wishing to know the full background behind my problem and what I have kind of tried as a result of input from this question, see this: http://pastebin.com/nTrEAkVj
我会经常编辑这个(>每天最平日3倍)我进步我的研究和情况,所以要检查回来,如果你有兴趣或有一些信息我的问题或knowlesdge:)
I will be editing this frequently (>3 times a day most weekdays) as I progress my research and situation, so keep checking back if you are interested or have some information or knowlesdge of my issue :)
快速背景:
我有这个程序,我已经提出,可以通过改变我的屏幕保护程序或锁定我的工作站坠毁,一般只要WM_WININICHANGE / WM_SETTINGSCHANGE消息发送给它。
I have this app I have made that can be crashed by changing my screen saver or locking my work station, and in general whenever a WM_WININICHANGE/WM_SETTINGSCHANGE message is sent to it.
如果我可以改变我的屏保一直崩溃我的应用程序,那么这样做的某些部分正在发送我的应用程序的某种信息(并不一定是Windows消息,我的意思是,在最一般意义上的信息),这又是灾难性我的应用程序。由于这个原因,我试图找到一种方法来阻止任何消息从我的申请正在处理中引起了我的问题。我知道这是不是着手解决的最好办法,所以你不必告诉我。看的backgroung信息或者问为什么,如果你烦恼(有一个很好的理由)。
If I can consistently crash my app by changing my screensaver, then SOME part of doing that is sending my app SOME kind of message (not necessarily a windows message, I mean message in the most general sense), which in turn is catastrophic to my application. Due to this, I am trying to find a way to block whatever message is causing my problem from being processed by my application. I am aware this isn't the best way to go about a solution, so you don't need to tell me. Look at the backgroung info or ask why if that bothers you (there is a good reason).
我的问题:
有几件事情,任何个人信息会帮助我解决我的问题,标记,根据相关(1是最相关的,3略少有用):
there are several things that any information about would help me solve my problem, labelled according to relevance (1 being most relevant, 3 slightly less helpful):
-
我想使用的WndProc()来过滤掉我的消息是这样的:
I am trying to use Wndproc() to filter out my message like this:
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 ...这不应该发生,如果它是worknig不当,shoudlnt返回任何东西,不应该吗?关于为什么这是不工作如我所料,以及如何使其工作将是非常有用的信息!
However, according to Windspector, the WM_WININICHANGE message is still being sent to my app (this makes sense), BUT it is also being returned with 0... this shouldn't be happening if it was worknig properly, it shoudlnt return anything, shouldnt it? Information regarding why this isn't working as I expected and how to make it work would be extremely helpful!
我也尝试过使用messagefilters:
I have also tried using messagefilters:
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处理方式:
and then adding to my mybase.load handling method:
Application.AddMessageFilter(新MyMessageFilter())
Application.AddMessageFilter(New MyMessageFilter())
然而,他们似乎只能过滤某些信息,以及诸如地雷消息不会陷入这些看似。关于如果是肯定不可能使用任何类型的过滤器,以赶上WM_消息,或者如果有可能的其他方式使用消息过滤器来实现我的目标也将是有帮助的信息。
however they appear to only filter certain messages, and messages such as mine are not caught in these apparently. information about if it is definately impossible to use any kind of filter to catch a WM_ message or if there are possibly other ways to use message filters to accomplish my goal would also be helpful.
在我可以改变我的屏幕保护程序发送任何类型的信息发送到我的应用程序有什么其他的方法(除了与message.msg = WM_WININICHANGE = 26这个窗口消息,我找到了)?有没有可能从改变我的屏幕保护程序,另一种消息的也是致命的?
in what OTHER ways (apart from this one windows message with message.msg = WM_WININICHANGE = 26 that I found) could me changing my screensaver send ANY kind of message to my application? is it possible that another kind of message from changing my screen saver is also fatal?
让我知道是否有关于我的情况,可能是有用的任何其他信息,我会尽我所能得到它!预先感谢您的任何帮助,您可以给:)
Let me know if there is ANY other information regarding my situation that may be useful, and I will do my best to get it! Thank you in advance for any help you can give :)
编辑:
看来,如果我只发了WM_CHANGESETTING消息,使我的程序等待过我发送的消息与sendmessagetimeout的超时长度,然后我的计划犯规崩溃......它出现的反应是什么崩溃我的程序。 .. 有趣。我肯定接近我的解决方案!我想多一点的测试应该让我找出一个方法,以确保我的程序不响应该消息。不过,任何想法都是AP preciated:)
It appears if I ONLY send the WM_CHANGESETTING message, and make my program wait over the timeout length of the sendmessagetimeout I sent the message with, then my program doesnt crash... it appears the RESPONSE is what is crashing my program... interesting. I am definately close to my solution! I'm thinking a little more testing should allow me to figure out a method to make sure my program does not respond to the message. still, any ideas are appreciated :)
编辑两个:
我发现了一些今天非常有前途的:我定义我的WndProc功能完全是这样的:
I discovered something VERY promising today: I defined my wndproc function exactly like this:
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消息:
And then I tried running my program, and then sending a WM_SETTINGCHANGE message using:
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, IntPtr.Zero, _
SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, IntPtr.Zero)
在其他程序中我做了。到底发生了什么,你问?好,我试了几次,每次的消息框会弹出(我选择它的话是微不足道的),然后我尝试过pressing等待不同的时间确定,然后我会看看发生了什么事我主要形式。那么很多的时候,没有什么是不同的,它仍然会崩溃。但是有时候,也许1/5次,该计划仍然会后respoding!然后,如果它这样做,我会尝试重新发送消息,然后再次,通常他们会在程序的同一运行过程中失败,第二次,但偶尔一次,关于另一个1/5倍似乎,程序wouldnt崩溃AGAIN 。然后在次我试图两次崩溃了。和它没有任何时候,它几乎总是那么永不死机,无论多少次,我试图发送消息,也不管我打开了MSGBOX后等了多久。
in another program I made. So what happened you ask? well I tried this several times, and every time the messagebox would pop up (the words I chose for it are insignificant), then I tried waiting different amounts of time before pressing ok, and then I would see what happened to my main form. Well a lot of the time, nothing was different, it would still crash. But occasionally, maybe 1/5 times, the program would still be respoding after! Then if it did, I would try sending the message again, and then again, usually they would fail the second time during the same run of the program, BUT occasionally again, about another 1/5 times it seemed, the program wouldnt crash AGAIN. And then the times I tried to crash it twice. and it didnt either time, it would almost always then never crash no matter how many times I tried sending the message and regardless of how long I waited after the msgbox popped up.
我发现等待约5秒钟,似乎增加我的优势:我的状态,我触发与仍然成为市场关注焦点(最上面一栏是蓝色的)消息,之后我pressed冻结按钮,然后MSGBOX将聚焦(至少是蓝色哈哈)弹出,与上方还蓝(焦点我认为),他们两人依然。然后,约5秒钟后,原来的形式会失去焦点,并看到那以后,我会尽力打好吧。
I found waiting about 5 seconds seemed to increase my odds: my form that I trigger the message with would still be in focus (top bar would be blue), right after I pressed the freeze button, and then the msgbox would pop up, with the top also blue (in focus I assume), both of them still "in focus" (at least blue haha). Then after about 5 seconds the original form would lose focus, and after seeing that, I would try hitting ok.
我目前认为这等待了一下,然后确认该消息框有时使我的程序不会崩溃,因为它是超时的消息,因此不会返回。我不知道为什么邮件退回或者不应该有什么我的程序实际上不会,虽然效果。这是澄清将是有益的领域:)
I am currently thinking that this waiting a bit and then acknowledging the message box is sometimes enabling my program to not crash because it is timing out the message so it does not return. I do NOT know why the message returning or not should have an effect on what my program actually does though. THis is the area where clarification would be helpful :)
这个任何想法将有助于!
Any idea about this would help!
修改三:
所以我期待在Winspector多一点,而且我发现,如果我等WM_ERASEBKGND展现在我的桌面窗口(这是标示为WinspectorsysListView32文件夹视图窗口)击球前,OK我MSGBOX,那么程序将不会崩溃,有意思!它通常需要接近的超时sendmessagetimeout为WM_ERASEBKGND消息露面。这当然是从我国产的测试应用程序发送WM_SETTINGCHANGE消息之后。
so I am looking in Winspector a bit more, and I find that if I wait for WM_ERASEBKGND to show up in my desktop window (which is the window labelled as "sysListView32 'FolderView'" in Winspector) before hitting "OK" on my msgbox, then the program will not crash, interesting! It usually takes close to the Timeout for the sendmessagetimeout for the WM_ERASEBKGND message to show up. this is of course after sending the WM_SETTINGCHANGE message from my homemade testing app.
那么,在这之后我决定找多一点左右Winspector,监守也许还有更有效的队列可以找到?由于明显的等待winspector显示一个消息发送到我的桌面是不是一个真正的修复都对我的计划。我找了几个不寻常名为Windows下我的计划进程:一种被命名为.NET -BroadcastEventWindow.2.0.0.0.378734a.0,另一个名为GDI +钩窗口类GDI +窗口有一个名为输入法子窗口默认输入法'。
So, after this I decide to look a bit more around Winspector, becuase maybe there are even more useful queues I can find? Since obviously waiting for winspector to show a message is sent to my desktop isn't an actual fix at all for my program. I find a few unusually named windows under my program process: one is named ".NET -BroadcastEventWindow.2.0.0.0.378734a.0" and another is named "GDI+ Hook Window Class 'GDI+ Window'" with a subwindow called "IME 'Default IME'".
我决定看看去这些窗口,看看他们是recieving任何可识别信息,如WM_SETTINGCHANGE或WM_ERASEBKGND的消息。事实证明,他们没有接受她的消息频繁:GDI +并没有接受她的任何消息,而我看着我不觉得,但是.NET -BroadcastEventWindow收到了一条数。那些要去BroadcastEventWindow大多只有WM_appactivate当我点击我的应用程序窗口或其他窗口后。
I decide to look at the messages going to these windows to see if they are recieving any recognizable messages, such as WM_SETTINGCHANGE or WM_ERASEBKGND. Turns out, they do not recieve messages often: GDI+ didn't recieve any messages while I watched I don't think, but .NET -BroadcastEventWindow recieved a few. The ones going to the BroadcastEventWindow were mostly only WM_appactivate when I clicked my application window or another window after it.
但后来......我发现净BroadcastEventWindow临危我WM_CHANGESETTING消息!!!!我看看其他的信息都显示什么:不是很多,但我注意到,当应用程序崩溃,因为错误的,有消息我不承认:WM_USER + 7194(0x201A)。嗯,让我们看看那是什么。当我谷歌,我找出这似乎是一个应用程序/用户定义的消息,然后对与此相关的问题的另一个搜索后,我注意到,有人能够使用过滤器来过滤此信息,并解决的问题他们(http://www.pcreview.co.uk/forums/handling-wm_user-messages-t1315625.html)。这是值得一试至少对我好吗?所以我重新加我试过previously过滤器,并改变要过滤的值。该应用程序并没有崩溃!!!!!!!
BUT THEN... I notice .Net BroadcastEventWindow recieves my WM_CHANGESETTING message!!!! I look at what other messages show up: not a lot, but I notice when the app crashes because of the bug, there is a message I don't recognize: WM_USER+7194 (0x201A). Hm, lets see what that is. After I google it, I figure out it appears to be an application/user defined message, and then after another search about problems related to it, I notice that someone is able to use a filter to filter this message out and fix a problem of theirs (http://www.pcreview.co.uk/forums/handling-wm_user-messages-t1315625.html). It's worth a try for me at least right? so I re-add the filter I had tried previously, and change the values to be filtered. The app didn't crash!!!!!!!
接下来,我尝试让我的工作站锁定,看看是否仍然崩溃它(因为previously只是用它发送孤WM_CHANGESETTING消息)。事实证明,它仍然没有崩溃:(但是,我再看看在winspector该窗口,呵呵呵呵,两个新WM_USER消息:WM_USER + 7294(0x207E)和WM_USER + 7189(0x2015),所以我尽量过滤那些出去。太...然后它不崩溃的工作站锁定要么!!!:D
Next I try by letting my workstation lock to see if that still crashes it (because previously was only with sending it the lone WM_CHANGESETTING message). turns out, it still did crash :( BUT, I take another look in winspector for that window, and oh huh, two NEW WM_USER messages: WM_USER+7294(0x207E) and WM_USER+7189(0x2015). So I try filtering those out too... and then it doesnt crash on workstation locking either!!! :D
到目前为止,我已经注意到了这个没有任何负面影响在普通的应用程序使用的呢!这是有道理的,因为我不认为任何用户定义的消息都有意参与我的计划。
So far I have noticed no adverse affects of this on regular app use too! which makes sense, since I don't think any user defined messages are purposefully involved in my program.
我将离开这个问题打开多一点的时间,直到我确定没有什么错我的解决方案,它工作得很好。感谢你们谁给我的建议有一点点如何继续在我调试的中间阶段:)
I will be leaving the question open a bit longer until I make sure there is nothing wrong with my solution and it works well. Thanks to those of you who gave me a little bit of advice with how to proceed at the middle stages of my debugging :)
我见过的各种问题,多年来提到了这个问题。从来没有完全确诊的话,我就告诉你,我知道这一点。
I've seen this problem mentioned in various questions over the years. Never completely diagnosed it, I'll just tell you what I know about it.
此问题与的方式SystemEvents类被初始化。据参与了事故,因为这是触发,当你切换到安全桌面触发该事件的类。既可以通过屏幕保护程序,或通过锁定工作站(的Windows + L键)。 WinForms控件是一般感兴趣的SystemEvents.DisplaySettingsChanged事件,因为他们可能需要重新绘制自己时,主题或系统颜色发生了变化。此事件在系统切换桌面也普遍提高。
This problem is related to the way the SystemEvents class gets initialized. It is involved in the mishap because that's the class that triggers the event that fires when you switch to the secure desktop. Either through the screen-saver or by locking the workstation (Windows + L key). Winforms controls are in general interested in the SystemEvents.DisplaySettingsChanged event because they might need to redraw themselves when the theme or the system colors were changed. This event is also commonly raised when the system switches desktops.
一个核心问题是,该事件所需要的UI线程上得到提升。 SystemEvents需要猜测完全的什么的线程实际上是UI线程。这当是在程序中创建的第一个窗口一个线程是不实际的UI线程,并以其他方式有其COM单元设置为STA伪装成一个创造出了问题。如果线程实际上一直然后运行该事件被触发该线程。如果线程消失了,并不少见,那么将引发一个例外,当SynchronizationContext.Post()尝试编组调用和失败。唯一的例外是吞噬,而该事件引发然后在任意的线程池线程。
One core issue is that the events needs to be raised on the UI thread. SystemEvents needs to guess exactly what thread is actually the UI thread. This goes wrong when the very first window that is created in the program is created on a thread that is not actually the UI thread and otherwise masquerades as one by having its COM apartment set to STA. If the thread actually keeps running then the event is fired on that thread. If the thread is gone, not uncommon, then an exception is raised when the SynchronizationContext.Post() tries to marshal the call and fails. The exception is swallowed and the event is then raised on an arbitrary threadpool thread.
无论哪种方式,该事件不会引发在正确的线程和违反任何UI组件穿线的要求。这往往会被忽视,一些奇怪的原因桌面交换机上相同触发的事件往往会更经常导致死锁或崩溃。
Either way, the event is not raised on the correct thread and that violates the threading requirements for any UI component. This tends to go unnoticed, for some strange reason the same event fired on the desktop switch tends to cause deadlock or crashes much more often.
您需要仔细审查程序的初始化code。截至目前,最常见的错误是创建自己的启动画面。一定要使用built-in在.NET框架的支持获得这一权利。
You'll need to carefully review the initialization code of the program. By far the most common mistake is creating your own splash screen. Be sure to use the built-in support in the .NET framework to get that right.