可能な解決策が見つかりました!
私は解決策を見つけたと信じています!実際に機能することを確認するためにテストを続けますが、期待しています:)質問のEDIT 3で解決策を見つけた方法を詳しく説明しました!
私の問題の背後にある完全な背景と、この質問からの入力の結果として私が試したことを知りたい人は、これを参照してください: http://pastebin.com/nTrEAkVj
私はこれを頻繁に編集します (ほとんどの平日は 1 日 3 回以上) 調査と状況を進めているので、興味がある場合、または私の問題に関する情報や知識がある場合は、チェックし続けてください :)
簡単な背景:
私が作成したこのアプリは、スクリーン セーバーを変更したり、ワーク ステーションをロックしたりすることでクラッシュする可能性があります。
スクリーンセーバーを変更してアプリを一貫してクラッシュさせることができる場合、その一部はアプリに何らかの種類のメッセージを送信しています (必ずしも 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_メッセージをキャッチするために何らかの種類のフィルターを使用することが絶対に不可能であるかどうか、またはメッセージフィルターを使用して私の目標を達成する他の方法があるかどうかについての情報も役立ちます.
スクリーンセーバーを変更すると、アプリケーションにメッセージを送信できますか? スクリーンセーバーの変更による別の種類のメッセージも致命的である可能性はありますか?
私の状況に関して他に役立つ情報があれば教えてください。それを得るために最善を尽くします! あなたが与えることができるどんな助けにも前もって感謝します:)
編集:
WM_CHANGESETTINGメッセージのみを送信し、メッセージを送信したsendmessagetimeoutのタイムアウトの長さを超えてプログラムを待機させた場合、プログラムはクラッシュしません... RESPONSEがプログラムをクラッシュさせているようです.. 。 面白い。私は間違いなく私の解決策に近づいています!もう少しテストすることで、プログラムがメッセージに応答しないことを確認する方法を見つけられるようになると思います。
編集2:
今日、非常に有望なものを発見しました。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)
私が作った別のプログラムで。それでどうしたの?私はこれを数回試しましたが、メッセージボックスがポップアップするたびに (選択した単語は重要ではありません)、[OK] を押す前にさまざまな時間待機してみました。多くの場合、何も変わらず、それでもクラッシュします。しかし、場合によっては、おそらく 1/5 回、プログラムがまだ応答していることがあります。もしそうなら、私はメッセージをもう一度送信しようとしますが、通常は同じプログラムの実行中に2回目に失敗しますが、時々もう一度、さらに約1/5回、プログラムは送信されませんでした.もう一度クラッシュします。そして、2回クラッシュさせようとしたとき。どちらも間に合いませんでした
約 5 秒待つと、オッズが高くなるように見えました。フリーズ ボタンを押した直後に、メッセージをトリガーするフォームにまだフォーカスがあり (上部のバーは青色)、メッセージボックスがポップアップします。上部も青(焦点が合っていると思います)、両方ともまだ「焦点が合っています」(少なくとも青笑)。すると5秒くらいで元のフォームからフォーカスがずれてきて、それを見てOKを打ってみたり。
私は現在、これを少し待ってからメッセージボックスを確認すると、メッセージがタイムアウトして返されないため、プログラムがクラッシュしないことがあると考えています。ただし、メッセージが返されるかどうかが、プログラムの実際の動作に影響する理由はわかりません。これは、明確化が役立つ領域です:)
編集 3:
そのため、Winspector でもう少し調べてみると、デスクトップ ウィンドウ (Winspector では「sysListView32 'FolderView'」というラベルの付いたウィンドウ) に WM_ERASEBKGND が表示されるのを待ってから、メッセージボックスで「OK」を押すことがわかりました。 、その後、プログラムはクラッシュしません、興味深いです! 通常、WM_ERASEBKGND メッセージが表示されるまでには、sendmessagetimeout のタイムアウトに近い時間がかかります。これはもちろん、自家製のテスト アプリから WM_SETTINGCHANGE メッセージを送信した後です。
それで、この後、Winspector についてもう少し調べることにしました。もっと便利なキューを見つけることができるのではないでしょうか? 明らかに、winspector がデスクトップに送信されるメッセージを表示するのを待つことは、プログラムの実際の修正ではありません。私のプログラム プロセスの下に、変わった名前のウィンドウがいくつか見つかりました。デフォルト IME'".
これらのウィンドウに送信されるメッセージを調べて、WM_SETTINGCHANGE や WM_ERASEBKGND などの認識可能なメッセージを受信しているかどうかを確認することにしました。結局のところ、彼らはメッセージを頻繁に受信するわけではありません.私が見ている間、GDI +はメッセージを受信しませんでしたが、.NET -BroadcastEventWindowはメッセージをいくつか受信しました. BroadcastEventWindow に移動するのは、自分のアプリケーション ウィンドウまたはその後に別のウィンドウをクリックしたときのほとんどが WM_appactivate だけでした。
しかし... .Net BroadcastEventWindow が WM_CHANGESETTING メッセージを受信していることに気付きました!!!! 他に表示されるメッセージを確認します。多くはありませんが、バグが原因でアプリがクラッシュしたときに、認識できないメッセージがあることに気付きました: WM_USER+7194 (0x201A)。うーん、それが何であるか見てみましょう。Google で調べたところ、アプリケーション/ユーザー定義のメッセージであることがわかりました。それに関連する問題についてもう一度検索したところ、誰かがフィルタを使用してこのメッセージを除外し、問題を修正できることに気付きました。彼らの ( http://www.pcreview.co.uk/forums/handling-wm_user-messages-t1315625.html )。少なくとも私にとっては試してみる価値がありますよね?そのため、以前に試したフィルターを再度追加し、フィルターする値を変更します。アプリはクラッシュしませんでした!!!!!!!!
次に、ワークステーションをロックして、それでもクラッシュするかどうかを確認してみます (以前は WM_CHANGESETTING メッセージを送信するだけだったからです)。結局、それでもクラッシュしました:(しかし、そのウィンドウのwinspectorをもう一度見てみると、ああ、2つの新しいWM_USERメッセージがあります:WM_USER+7294(0x207E)とWM_USER+7189(0x2015)。あまりにも...そして、ワークステーションのロックでもクラッシュしません!!! :D
これまでのところ、これが通常のアプリの使用にも悪影響を及ぼしていないことに気付きました! ユーザー定義メッセージが私のプログラムに意図的に関与しているとは思わないので、これは理にかなっています。
私の解決策に問題がなく、うまく機能することを確認するまで、質問をもう少し開いたままにします。デバッグの中間段階でどのように進めるかについて少しアドバイスをくれた皆さんに感謝します:)