3

win32 に次のコードがあり、ターゲット アプリケーションにフックを設定します。

void InstallHook(DWORD ThreadId)
{
    g_hHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, g_hInstDll, ThreadId); 
}

この関数を C# (.net) から呼び出したいと考えています。

私はこれまでのところこれを持っています:

[DllImport("TheHookDll.dll")]
public extern static void InstallHook(UInt32 ThreadId);

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

そして私はそれを次のように呼びます:

IntPtr hWnd = FindWindow(null, "MyTargetAppWindowTitle");

UInt32 threadID = GetWindowThreadProcessId(hWnd, IntPtr.Zero);

InstallHook(threadID);

これにより、ターゲットのハンドル (hWnd) と、win32 の InstallHook 関数で使用されるスレッド ID が得られます。(16進数ではなく10進数です)

しかし、次のエラー メッセージが表示されます。

PInvokeStackImbalance が検出されました メッセージ: PInvoke 関数 'TheOperator!TheOperator.Form1::InstallHook' の呼び出しにより、スタックのバランスが崩れました。これは、マネージド PInvoke 署名がアンマネージド ターゲット シグネチャと一致しないことが原因である可能性があります。PInvoke シグネチャの呼び出し規約とパラメーターがターゲットのアンマネージド シグネチャと一致することを確認します。

dll ファイルの呼び出し規約 (構成プロパティ -> C/C++ -> すべてのオプション -> 呼び出し規約) を __cdel から __stdcall に変更しようとしましたが、うまくいきませんでした。(同じエラー)

私は何を間違っていますか?

C#はDWORDなどをサポートしていないため、DWORDをUInt32に変更しましたが、それは正しい方法ですか?

ヒントはありますか?

4

1 に答える 1

1

次のように PInvoke を定義します。

    [DllImport("TheHookDll.dll", CallingConvention = CallingConvention.Cdecl)]
    public extern static void InstallHook(UInt32 ThreadId);

この特定の関数を呼び出すと、呼び出し元がスタックをクリーンアップする必要があるためです。これを PInvoke 署名で明示的に指定しないと、ランタイムはスタックをクリーンアップしないため、スタックがめちゃくちゃになり、表示されているエラー メッセージが表示されます。

を明示的に指定しない場合CallingConvention、ランタイムは、呼び出そうとしている関数が であると想定しStdCall、呼び出し先がスタックを消去します。そうではなく、スタックはすべてめちゃくちゃで汚れたままになります。

それ以外は、署名が正しいように見えます。aDWORDは確かに C#の auintまたはです。UInt32それが問題になる場合は、MarshalAs属性で装飾して、元帥に unmanaged type として返させることができますU8

于 2013-07-11T21:39:26.163 に答える