3

サーバー上の提供されたアプリケーションを監視するための単純な C# アプリを作成しています。メッセージ ボックスに特定のウィンドウ名が表示された場合は、ウィンドウを閉じてプロセスを続行します。ベンダーは、情報メッセージ ボックスがランダムに表示され、X または OK ボタンがクリックされるまでアプリケーションをハングさせます。2 種類のメッセージ ボックスが表示され、1 つはアプリケーションを使用して問題なく閉じられますが、もう 1 つは閉じられません。どちらも非常によく似ており、メッセージの一部として SQL テキストが埋め込まれているだけです。どちらのメッセージ ボックスも FindWindow によって検出されます。SendMessage が実行されると、2 番目のタイプのメッセージ ボックスが表示されても閉じられません。PostMessage も試しましたが、同じ問題が発生します。

これは私が持っているものです:

    private const int WM_CLOSE = 0x10;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    IntPtr ErrorPopUp = FindWindow(null, WindowToClose.Trim());
                        if (ErrorPopUp != IntPtr.Zero) {
                            try {
                                Thread.Sleep(200);
                                SendMessage(ErrorPopUp, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                                _WMExceptionDal.LogErrorMsg(_WMException);

                            } catch (Exception ex) {
                                _WMException.txt_iferror = "Unable to close the popup window";
                                _WMException.txt_sqlerrtext = ex.ToString();
                                _WMExceptionDal.LogErrorMsg(_WMException);
                            }
                        }

他のアプローチの提案、または一部のメッセージボックスが WM_CLOSE によって閉じられる理由と、一部のメッセージボックスが閉じられない理由について何か間違ったことをしている場合は、本当に感謝しています。

4

1 に答える 1

1

答えはあなたが思っているよりも簡単です。エラーに対して表示されるポップアップには「OK」ボタンがあり、ウィンドウのタイトル バー領域に「閉じる」ボタンはありません。

それらは非常に原始的です。ウィンドウ プロシージャのメッセージ処理は、ダイアログ ボタンの背後にある関数に限定されます。

SendMessage(ErrorPopUp, WM_COMMAND, IDOK, IntPtr.Zero);

あなたがそれを送信した場合、WM_CLOSE家に誰もいません。そのメッセージに応答するウィンドウのメッセージハンドラーには何もありません。はい、すべてのウィンドウWM_CLOSEもメッセージに応答すると思っていた時期がありました。

他のスレッドからの「閉じる」メッセージに応答するダイアログ ウィンドウにも制限がありますが、ここで起こっていることではないと思います。(ただし、ダイアログ ボックスのタイトル バーにダイアログ ボックスを閉じるための「x」ボタンがあり、メッセージに応答しない場合WM_CLOSEは、これが最も可能性の高い説明です)。

いずれにせよ、間違ったメッセージを送信しています。ダイアログは、ボタンにリストされたユーザー入力に応答するために作成されました。これらは、WM_COMMANDメッセージ識別子を使用して送信するメッセージです。

private const int WM_COMMAND = 0x111;
private const int dlgOK = 0x1; private const int dlgCANCEL = 0x2; private const int dlgABORT = 0x3; private const int dlgRETRY = 0x4; private const int dlgIGNORE = 0x5; private const int dlgYES = 0x6; private const int dlgNO = 0x7;

「どの識別子?」という質問 通常は無関係です - ここでは「OK」です - しかし、User32 関数GetDlgItem()は、確認する必要がある場合に、どのダイアログ ボックス機能が存在するかを確認します。

また、「キャンセル」ボタンのあるダイアログに注意してください。ダイアログには、ウィンドウ メニューを有効にし、タイトル バーに閉じる「x」ボタンを表示するキャンセル機能の実装があり、これらの実装の一部WM_CLOSEは、メッセージ (彼らも応答する必要 WM_SYSCOMMAND, SC_CLOSEがあります); しかし、 以外のものに頼るのは賢明ではありませんWM_COMMAND, dlgCANCEL

于 2016-02-01T21:59:17.477 に答える