Ошибка SetWindowsHookEx с ошибкой 126

я пытаюсь использовать Gma.UserActivityMonitor библиотека в проекте, и я столкнулся с ошибкой, которую я не могу преодолеть самостоятельно.

на HookManager.Callbacks.cs file существует статический метод под названием EnsureSubscribedToGlobalMouseEvents со следующим кодом (более или менее):

var asm = Assembly.GetExecutingAssembly().GetModules()[0];
var mar = Marshal.GetHINSTANCE(asm);
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE_LL,
    s_MouseDelegate,
    mar,
    0);
//If SetWindowsHookEx fails.
if (s_MouseHookHandle == 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

    //Initializes and throws a new instance of the Win32Exception class with the specified error. 
    throw new Win32Exception(errorCode);
}

на SetWindowsHookEx всегда возвращает 0 и вышеуказанный код продолжает бросать исключение с сообщением The specified module could not be found, а вызов Marshal.GetLastWin32Error возвращает код 126. Я могу успешно запустить демо-версию с ГМа.Оригинальный проект UserActivityMonitor, но поскольку мой проект слишком сложен, чтобы объяснить здесь, я не могу подробно объяснить его разницу с моим. Я просто надеюсь, что кто-то может слепо догадаться о проблеме.

кстати, в FAQ проекта говорится, что у других есть проблема, близкая к моей (с SetWindowsHookEx ошибка), когда Enable Visual Studio hosting process проверяется только при отладке проекта. Поэтому я снял этот флажок в своем, и все же у меня такая же проблема, а не просто в режиме отладки, но и когда я дважды щелкните файл выпуска в Проводнике Windows(без Visual Studio).

чтобы дать больше информации, в демо-проекте (который отлично работает)asm переменной {Gma.UserActivityMonitor.dll} и то же самое в моем проекте, в котором выбрасывается исключение!

1 ответов


этот код больше не работает на .NET 4 и выше. Код ошибки, который вы получаете, в противном случае описателен, 126 = "указанный модуль не найден". Что говорит вам, что переменная" mar " содержит мусор.

.NET 4 имел довольно значительное изменение среды CLR, он больше не притворяется, что jitted-код живет внутри неуправляемых модулей. Так Маршал.GetHINSTANCE () больше не работает. Затем код становится небрежным, он забывает проверить возвращаемое значение, проверяя его на (IntPtr)-1 требуется для обнаружения сбоя и объявления бедствия. Довольно распространенный для кода, который вы найдете в Codeproject, много ошибок и небрежности, которые не могут быть исправлены участниками. Не так модель:)

SetWindowsHookEx () немного неудобно для низкоуровневых крючков. Он требует допустимого дескриптора модуля и проверяет его, но фактически не использует его. Это было исправлено в Windows, где-то вокруг Win7 SP1. Хотя это, безусловно, должно было быть полезным исправлением, на самом деле это усугубило проблему. Потому что сейчас он может работать на вашем компьютере dev, но не на компьютере пользователя.

Anyhoo, исправление простое, вам просто нужно кашлянуть допустимый дескриптор модуля. Вы можете получить его из модуля, который всегда присутствует в управляемом приложении, вам нужно вызов PInvoke функцию LoadLibrary чтобы получить его:

var mar = LoadLibrary("user32.dll");
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE_LL,
    s_MouseDelegate,
    mar,
    0);

нет необходимости вызывать FreeLibrary (), этот модуль остается загруженным, пока ваша программа не завершится в любом случае.