8

たくさんのことを試しましたが、タスクバーが非表示になったり、デスクトップ UI に他の超自然的な効果が表示されたりする中で、一貫して動作させることができません。

最初にオープン ライブラリhttp://mwinapi.sourceforge.net/を使用してみました。ウィンドウなどを列挙するためのOOレイヤーとしてはうまく機能しましたが。フックを適切に実行できませんでした

次の目的地は、.Net フレームワークの Windows フックに関する Dino E. の投稿でした。テキストを理解し、これを機能させようとしていたので、私は自分のタイプを書くことになりました。

私の意図は、このアプリを実行し、実行中に作成されたすべてのウィンドウをログに記録できるようにすることです。すべての目玉を呼んでいます...

更新:どうやら.Net / マネージ コードでグローバル ウィンドウ フックを記述できないため、切り捨てました(一部の低レベルのマウスまたはキーボード フックを除く) 。

そこで、C++ に切り替えました。それでも、すべての WinAPI 呼び出しは有効なハンドルを返しますが、フィルター関数が呼び出されていません。通知を受け取っていないようです。それでもうまくいきません...誰かが間違いを見つけることができますか。

void CWinHookFacade::Hook()
{
    HMODULE hCurrentDll = LoadLibrary(_T("[Path to my hook dll]"));
    m_HookHandle = SetWindowsHookEx(WH_CBT, 
        FilterFunctionForHook, 
        hCurrentDll, 
        0);
    if (m_HookHandle == NULL)
    {
        throw new std::exception("Unable to hook");
    }

}
void CWinHookFacade::Unhook()
{
    if (!UnhookWindowsHookEx(m_HookHandle))
    {
        throw new std::exception("Unhook failed!");
    }
    m_HookHandle = NULL;
}

LRESULT CWinHookFacade::FilterFunctionForHook(int code, WPARAM wParam, LPARAM lParam)
{
    if (code >= 0)
    {
        switch(code)
        {
        case HCBT_CREATEWND:
            wprintf(_T("Created Window"));
            break;
        case HCBT_ACTIVATE:
            wprintf(_T("Activated Window"));
            break;
        case HCBT_DESTROYWND:
            wprintf(_T("Destroy Window"));
            break;
        }
    }

    return CallNextHookEx(m_HookHandle, code, wParam, lParam);
}

クライアント exe は次のように Hook_DLL を呼び出します

int _tmain(int argc, _TCHAR* argv[])
{
    CWinHookFacade::Hook();
    getchar();
    CWinHookFacade::Unhook();
}
4

2 に答える 2

7

あなたが抱えている問題は、C# でフック関数を実装しようとしているからだと思います。の pinvoke.net のドキュメントに基づいてSetWindowsHookEx()、これを行うことはできないと書かれています - フック プロシージャはアンマネージ DLL にある必要があります。そうしないと、実行中のすべてのプロセスに DLL が読み込まれ、メッセージ ループが発生し、各プロセスで CLR が読み込まれて開始されます。これには時間がかかるだけでなく、すべてのプロセスに CLR を挿入することはおそらく最善の方法ではありません。さらに、DLL が構築された対象とは異なる実行中の CLR がプロセスに既にある場合はどうなるでしょうか。

最善の方法は、このコードをアンマネージ C++ DLL に移動し、何らかのプロセス間通信を使用して、フック プロシージャによってインターセプトされたデータをアプリケーションに送り返すことです。

アップデート

最初に (これはおそらく問題の原因ではありません)、 DLLLoadLibrary()を取得するために呼び出しているのはなぜですか? DLL が既に読み込まれているため、おそらくGetModuleHandle()HINSTANCEを呼び出した方がよいでしょう。

フックプロシージャが呼び出されない理由について-これをどのように確認しましたか? システム内のすべての GUI スレッドをフックしているため、これは、DLL をすべての GUI プロセスにロードする必要があることを意味します。wprintf()他のプロセスには出力を表示するためのコンソール ウィンドウがないため、呼び出しの結果が表示されない可能性があります。

DLL が適切にロードされていることを確認するには、プロセスによってロードされた DLL を一覧表示するプログラムを使用します (私はProcess Explorerが好きです)。検索を使用できます | ハンドルまたは DLL メニュー項目を検索して、DLL の名前を検索します。これは、メッセージ ループですべてのプロセスに表示されます。

DLL が読み込まれていることを確認したら、フックが呼び出されるかどうかを確認するために、デバッガーを別のプロセス (メモ帳など) にアタッチし、フック関数にブレークポイントを設定します。これは、メッセージが CBT フックに送信されるたびにオフになるはずです。デバッガーを使用したくない場合は、呼び出しをwprintf()OutputDebugString ()に変更し、 DebugViewなどのユーティリティを実行して結果を監視できます。

最後に、フック関数は別のプロセスのコンテキストで呼び出されるため、m_HookHandle変数はそこでは有効になりません。読み込まれた DLL のすべてのインスタンスが同じ値を持つように、共有データ セグメントに格納する必要があります。

于 2009-06-08T12:21:43.073 に答える
6

最後にこれを釘付けにしました。将来誰かがこれを必要とする場合に備えて、ブログ投稿として書きました。

于 2009-06-16T06:38:44.653 に答える