我需要一个全局系统挂钩,它将拦截 GDI 并从应用程序获取屏幕上的所有文本。我按照此处的说明执行此操作: https ://msdn.microsoft.com/en-us/library/windows/desktop/ms644960(v=vs.85).aspx#installing_releasing
到目前为止的代码:
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 位程序崩溃,这是可以预料的,但不是我需要的行为。那么,为什么它让我拦截整个库,而不是特定的程序?我应该怎么做才能让它正确并在它出现在屏幕上之前阅读系统范围内的所有文本?