Я нашел похожие вопросы на этой странице, но я не могу понять, как интерпретировать ответы или выяснить, действительно ли они дублируются.
Вот возможные дубликаты, которые я нашел, с комментариями:
SetWindowsHookEx возвращает 0 при компиляции для .NET 4. 0 на 32-битных машинах
Кажется, он не возвращает 0 на моем, но я заметил, что дескриптор, сообщаемый при сбое (.NET 4.0 на 32-битных), сильно отличается от дескриптора, сообщаемого при его запуске (. NET 3.5 на 32-разрядной версии), например дескриптор сбоя = 523727 и рабочий дескриптор = 172738378.
Вызов SetWindowsHookEx внутри отладчика VS2008 всегда возвращает NULL
Я могу воспроизвести свою проблему при работе вне Visual Studio
Это кажется наиболее многообещающим, за исключением того, что в комментариях к удаленному ответу упоминается, что я должен использовать LoadLibrary и GetProcAddress для загрузки user32.dll в .NET 4.0, поскольку кое-что изменилось в загрузке сборок. Однако я почти уверен, что это мой собственный модуль, который он не может найти, но я не знаю, применимо ли это.
Рассматриваемые комментарии к удаленному ответу на последний, Автор Hans Passant, читает:
Вы используете .NET 4.0? Его среда CLR изменила способ загрузки сборок, больше нет вызова LoadLibrary, для них не будет дескриптора модуля. Еще одним исправлением было бы использование GetEntryAssembly (). - Ханс Пассан 5 мая в 19:43
Итак, что здесь за слово? Вы используете .NET 4.0? Вы пытались использовать LoadLibrary ("user32.dll"), чтобы получить доступный дескриптор DLL? - Ханс Пассан, 6 мая, 15:43
Я почти уверен, что мне не нужно этого делать, но, очевидно, я не уверен на 100%. Вопрос, который у меня остается, если мне нужно это изменить, заключается в том, почему он работает в 64-битной ОС при компиляции для Any CPU
, но не работает в 32-битной ни в какой конфигурации.
Если что-то действительно изменилось в загрузке сборок .NET, так что я не могу правильно описать библиотеку классов, У меня есть следующие вопросы:
Предпосылки
Я создал программу в .NET 4.0, которая использует SetWindowsHookEx с типом ловушки WH_KEYBOARD_LL для захвата нажатий клавиш. Это нормально работает на моей 64-битной Windows 7, но вылетает с сообщением «модуль не найден», когда клавиатурный захват установлен в 32-битной Windows 7.
Вот что я пробовал:
Я бы предпочел не переключать свой код на .NET 3.5, так как я использую несколько моих библиотек классов для облегчения работы, а последний код находится только в .NET 4.0.
Вы можете загрузить .ZIP-файл со всем в виде проекта Visual Studio 2010 , если хотите, или вы можете вставить следующие два файла.
Чтобы воссоздать, если вы хотите пойти по этому пути:
Затем собрать и запустить, протестировать различные конфигурации.
using System;
using HookLib;
namespace HookTest
{
class Program
{
static void Main()
{
var hook = new Hook();
Console.Out.WriteLine("hooking");
hook.Enable();
Console.Out.WriteLine("hooked");
Console.Out.WriteLine("unhooking");
hook.Disable();
Console.Out.WriteLine("unhooked");
}
}
}
using System;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
namespace HookLib
{
public class Hook
{
private IntPtr _Handle;
private HookProcDelegate _Hook;
public void Enable()
{
Module module = Assembly.GetExecutingAssembly().GetModules()[0];
if (module != null)
Console.Out.WriteLine("found module");
IntPtr moduleHandle = Marshal.GetHINSTANCE(module);
if (moduleHandle != IntPtr.Zero)
Console.Out.WriteLine("got module handle: " +
moduleHandle.ToString());
_Hook = HookProc;
_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, _Hook, moduleHandle, 0);
if (_Handle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
public void Disable()
{
bool ok = UnhookWindowsHookEx(_Handle);
_Handle = IntPtr.Zero;
if (!ok)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
private delegate int HookProcDelegate(
int code, IntPtr wParam, IntPtr lParam);
private int HookProc(int code, IntPtr wParam, IntPtr lParam)
{
return CallNextHookEx(_Handle, code, wParam, lParam);
}
private const int WH_KEYBOARD_LL = 13;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(
int hookType, HookProcDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true)]
private static extern int CallNextHookEx(
IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
}
}