Я постараюсь ответить на мой вопрос как можно более подробно, чтобы другие новички могли понять, что происходит.
Прежде всего, я следовал руководству по созданию хуков из Документация по хукам MSDN, но пример показывает его использование на c ++.Поиск ссылок на использование SetWindowHookEx
примеров, о которых я читал, касался перехвата низкоуровневых хуков окон.Эти хуки, а именно WH_KEYBOARD_LL
и WH_MOUSE_LL
, являются наиболее распространенными уроками и могут быть глобально перехвачены без необходимости разделения их процесса хука в dll.Остальные WH System Events
требуют разделения, если они должны быть подключены глобально.Это также описано в документации:
Вы должны поместить глобальную подключаемую процедуру в DLL отдельно от приложения, устанавливающего подключаемую процедуру.Устанавливающее приложение должно иметь дескриптор модуля DLL, прежде чем оно сможет установить процедуру подключения.
Грубая идея заключается в том, что функция подключения вставляется во все запущенные потоки.Для случая WH_KEYBOARD_LL
и WH_MOUSE_LL
, которые используют User32.dll
в качестве своей библиотеки ловушек, это хорошо.Но если бы вы использовали его для других системных событий, как я, этот процесс мог привести к сбою всего вашего рабочего стола, например, как это случилось с моим.
Мое приложение было написано на C #, поэтому мне пришлось создать dllв C ++, а затем связать его с моим приложением C #.Также прочитайте о pInvokes
, чтобы иметь возможность использовать LoadLibrary
и GetProcAddress
. Вы можете создавать dll
файлы из самой Visual Studio.Вам нужно только изменить файл dllmain.cpp.Я поигрался с WH_GETMESSAGE
из этого примера
Из моего приложения C # все, что мне нужно было сделать, это вызвать функцию SetHook
следующим образом:
IntPtr hInstance = IntPtr.Zero;
IntPtr hProc = IntPtr.Zero;
private delegate void HookSetting();
public void SetHook()
{
hInstance = LoadLibrary("Dll1");
if (IntPtr.Zero == hInstance)
{
//do a null check
}
hProc = GetProcAddress(hInstance, "_SetHook@0"); // SetHook is in its "mangled" form right here
if(IntPtr.Zero == hProc)
{
//do a null check
}
//Ways of starting the Hook:
// OPTION 1: calling the SetHook function of the DLL within the C# app.
//HookSetting hookset = (HookSetting)Marshal.GetDelegateForFunctionPointer(hProc, typeof(HookSetting));
//hookset();
// OPTION 2: Instead of using the SetHook function, call the SetwindowsHookEx directly
hhook = SetWindowsHookEx(WH_GETMESSAGE, hProc, hInstance, 0);
}