10

アプリケーションにフォーカスがない場合でも、押​​された3つのキーを取得するように低レベルのWindowsキーボードフックを設定しようとしています。これを行うために、私はSetWindowsHookExを次のように呼び出しています

// Create an instance of HookProc.
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
//install hook
hKeyboardHook = SetWindowsHookEx(
    WH_KEYBOARD_LL,
    KeyboardHookProcedure,
    Marshal.GetHINSTANCE(
        Assembly.GetExecutingAssembly().GetModules()[0]),
    0);
//If SetWindowsHookEx fails.
if (hKeyboardHook == 0)
{
    //Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set. 
    int errorCode = Marshal.GetLastWin32Error();
    //do cleanup
    Stop(false, true, false);
    //Initializes and throws a new instance of the Win32Exception class with the specified error. 
    throw new Win32Exception(errorCode);
}

これは、.NET Framework 3.5を使用する32ビットおよび64ビットマシンで機能していましたが、.NET Framework 4.0にアップグレードした後、32ビットマシンでは機能しなくなりました。

4.0 Frameworkを使用して、32ビットマシンと64ビットマシンの両方でこれを機能させるために、これを解決する方法を知っている人はいますか?

4

4 に答える 4

26

次のようにdllをインポートします。

[DllImport("kernel32.dll")]
    public static extern IntPtr GetModuleHandle(string name); 

次に使用します

GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName)

交換する

Marshal.GetHINSTANCE(
    Assembly.GetExecutingAssembly().GetModules()[0]
于 2012-06-29T03:43:05.487 に答える
2

SetWindowsHookExのドキュメントから

hMod [in]
HINSTANCElpfn
パラメーターが指すフックプロシージャを含むDLLへのハンドル。dwThreadIdパラメーターが現在のプロセスによって作成されたスレッドを指定し、フックプロシージャが現在のプロセスに関連付けられたコード内にある場合は、hModパラメーターをNULLに設定する必要があります。

したがって、NULLの場合はIntPtr.Zeroを渡す必要があります

//install hook
  hKeyboardHook = SetWindowsHookEx(
    WH_KEYBOARD_LL,
    KeyboardHookProcedure,
    IntPtr.Zero,
    0);
于 2010-09-22T19:30:05.130 に答える
1

各プラットフォームを個別にターゲットにして解決しました。Win32バージョンとWin64バージョンの両方をコンパイルし、対応するバイナリをx86およびx64マシンにデプロイするようにVSを構成しました。

Win32またはx86は、32ビットマシンと64ビットマシンの両方で動作します。

于 2010-08-30T16:19:25.343 に答える
0

ハンス・パッサント

低レベルのフックには実際には使用されないため、どのモジュールハンドルでもかまいません。それらを機能させるためにDLLを挿入する必要はありません。.NET 4では、CLRが純粋なマネージアセンブリのモジュールハンドルを偽造しなくなったため、1つを選択する際には注意が必要です。使用するのに適したものは、LoadLibrary( "user32.dll")をピンボーキングすることで得られるものです。これは、常にすでにロードされているためです。FreeLibrary()を呼び出す必要はありません。

LoadLibraryを呼び出すには、次の宣言が必要です。

[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string fileName);
于 2014-02-20T10:10:39.303 に答える