在32位计算机上编译.NET 4.0框架时,SetWindowsHookEx返回0

时间:2010-08-25 15:47:01

标签: c#-4.0 com-interop keyboard-hook setwindowshookex

即使应用程序未对焦,我也试图设置一个低级别的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 个答案:

答案 0 :(得分:23)

像这样导入dll:

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

然后使用

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

替换

Marshal.GetHINSTANCE(
    Assembly.GetExecutingAssembly().GetModules()[0]

答案 1 :(得分:2)

来自SetWindowsHookEx

的文档

hMod [in]
HINSTANCE
DLL的句柄,包含lpfn参数指向的钩子过程。如果dwThreadId参数指定当前进程创建的线程,并且钩子过程位于与当前进程关联的代码内,则必须将hMod参数设置为NULL。

所以你应该在IntPtr.Zero中传递NULL

//install hook
  hKeyboardHook = SetWindowsHookEx(
    WH_KEYBOARD_LL,
    KeyboardHookProcedure,
    IntPtr.Zero,
    0);

答案 2 :(得分:1)

通过单独定位每个平台解决了这个问题。配置VS以编译Win32和Win64版本,并在x86和x64机器上部署相应的二进制文件。

Win32或x86在32位和64位计算机上运行。

答案 3 :(得分:0)

Hans Passant

  

任何模块句柄都可以,因为它实际上并没有被使用   低级钩子,不​​需要注入DLL来使它们工作。一些   因为不再使用CLR,因此.NET 4需要注意选择一个   用于纯托管程序集的fakes模块句柄。一个好用的是   你可以通过pinvoking LoadLibrary(“user32.dll”)得到的   总是已加载。您不必调用FreeLibrary()。

     

您需要此声明才能调用LoadLibrary:

[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string fileName);