SetWindowsHookEx выдает ошибку 126: модуль не найден, когда
Мне нужен глобальный системный хук, который будет перехватывать GDI и получать весь текст на экране из приложения. Я делаю это, следуя инструкциям здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644960(v=vs.85).aspx
Код до сих пор:
import ctypes
import atexit
import time
import sys
from ctypes import wintypes, CFUNCTYPE, POINTER, c_int, c_uint, c_void_p, windll, pointer, byref, WinError
import win32con
WH_GETMESSAGE = 3
WH_CALLWNDPROC = 4
cmp_func = CFUNCTYPE(c_int, c_int, wintypes.HINSTANCE, POINTER(c_void_p))
gdi_dll = getattr(ctypes.cdll, 'Gdi32')
SetWindowsHookExA = ctypes.windll.user32.SetWindowsHookExA
SetWindowsHookExA.restype = wintypes.HHOOK
SetWindowsHookExA.argtypes = [c_int, cmp_func, wintypes.HINSTANCE, wintypes.DWORD]
UnhookWindowsHookEx = ctypes.windll.user32.UnhookWindowsHookEx
def _callback_pointer(handler):
"""Create and return C-pointer"""
print('handler=',cmp_func(handler))
return cmp_func(handler)
def callback(*args, **kwargs):
print(args, kwargs)
res = windll.user32.CallNextHookEx(*args, **kwargs)
print(res)
return res
hinstDLL = ctypes.windll.LoadLibrary('Gdi32')._handle
print('hinstDLL=', hinstDLL)
ctypes.windll.kernel32.GetProcAddress.restype = c_int
ctypes.windll.kernel32.GetProcAddress.argtypes = [c_int, ctypes.c_char_p]
hkprcSysMsg = ctypes.windll.kernel32.GetProcAddress(hinstDLL, "TextOutA".encode(encoding='ascii'))
if not hkprcSysMsg:
error = ctypes.windll.kernel32.GetLastError()
print(WinError(error))
print('hkprcSysMsg=', hkprcSysMsg)
hook = ctypes.windll.user32.SetWindowsHookExA(
WH_CALLWNDPROC,
_callback_pointer(callback),
hkprcSysMsg,
# hinstDLL,
0
)
print('hook=',hook)
error = ctypes.windll.kernel32.GetLastError()
print(WinError(error))
if not hook:
sys.exit()
while True:
_process_win_msgs() #not included in this question
time.sleep(0.02)
atexit.register(UnhookWindowsHookEx, hook)
Это последовательно получает меня
Ошибка 126: модуль не найден.
Но если я заменю hkprcSysMsg
с hinstDLL
Хук устанавливает и, кажется, работает, хотя все, что он делает, это приводит к сбою всех 32-битных программ, к которым я прикасаюсь во время работы, что вполне ожидаемо, но не такое поведение, которое мне нужно. Итак, почему это позволяет мне перехватить всю библиотеку, но не конкретную процедуру? Что я должен сделать, чтобы сделать это правильно и прочитать весь текст в масштабе всей системы, прежде чем он появится на экране?