我正在尝试使用Python类型来调用kernel32库上的GetModuleHandleA。我想获得一个库的句柄,这样我就可以使用它来调用LoadLibraryA的GetProcAddress。下面是我的代码..。
import sys
from ctypes
kernel32 = windll.kernel32
print("The kernel32 is %s" % kernel32)
#The kernel32 is <WinDLL 'kernel32', handle 765b0000 at 1c2a9f0>
h_kernel32 = kernel32.GetModuleHandleA("C:\\Windows\\System32\\kernel32.dll")
if h_kernel32 == False:
error = GetLastError()
print("ERROR: %d - %s" % (error, FormatError(error)))
我得到一个错误,“错误: 126 -找不到指定的模块”。我也尝试过"C:/Windows/System32/kernel32.dll“和"kernel32”。我使用的是Python 3.2,这是在Windows 7机器上。我已经验证了dll在那里,并且位于我在上面的代码中设置的路径中。我已经做了一些研究,但似乎找不到问题所在。任何帮助都是非常感谢的。谢谢!
发布于 2013-06-10 23:02:51
句柄存储在kernel32._handle
中。调用GetModuleHandle
应该返回相同的值,但请确保为类型安全设置了restype
和argtypes
*
import ctypes
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
kernel32.GetModuleHandleW.restype = wintypes.HMODULE
kernel32.GetModuleHandleW.argtypes = [wintypes.LPCWSTR]
hMod = kernel32.GetModuleHandleW('kernel32.dll')
注意“W”后缀而不是“A”。Python3使用Unicode字符串,ctype为其创建一个c_wchar_p
(LPCWSTR
)。没有理由调用ANSI版本,因为它只是宽字符串版本的包装器。但是如果你必须这样做,那么你需要使用字节:
kernel32.GetModuleHandleA.restype = wintypes.HMODULE
kernel32.GetModuleHandleA.argtypes = [wintypes.LPCSTR]
hMod = kernel32.GetModuleHandleA(b'kernel32.dll')
*建议您不要使用windll.kernel32
,而使用kernel32 = WinDLL('kernel32', use_last_error=True)
。这样可以避免与其他使用windll
的模块发生冲突。它还支持对线程的LastErrorValue
进行保护。这种情况下,请使用ctypes.get_last_error()
和ctypes.set_last_error(err)
,而不是直接调用WinAPI GetLastError
和SetLastError
。
发布于 2021-04-19 02:38:22
至于它是如何在内部完成的,ctypes.windll.kernel32
是WinDLL("kernel32")
。WinDLL继承了CDLL,CDLL的__init__
打开了kernel32的句柄。当您在kernel32
上使用字符串化属性"GetModuleHandle"
时,CDLL__getattr__
会查找该属性,并为其创建一个_FuncPtr
,它继承了_CFuncPtr
,这是一个_ctypes.CFuncPtr
。
python类型对象(PyTypeObject
)是在C中直接创建的,而不是通过定义python类(运行时将为其创建类型对象)间接创建的。请记住,运行时为python中的所有对象(包括函数)创建PyObject
,并为所有类型创建一个PyTypeObject
。因为CFuncPtr
是继承的,所以它定位CFuncPtr
类型对象中的构造函数,该对象在初始化类型对象时在C中设置为PyCFuncPtr_new
,该对象接受参数,在本例中为kernel32 WinDLL对象和"GetModuleHandle"
,并调用PyCFuncPtr_FromDll
以使用GetProcAddress
获取地址,该句柄指向在CDLL __init__
中设置的模块。在我看来,CDLL __init__
中的_dlopen
从内部创建的类型对象为kernel32创建了一个句柄对象,该对象调用内部C构造函数来执行类似LoadLibrary
的操作,并通过python代码将相关的PyObject
分配给kernel32 WinDLL PyObject中的self._handle
,然后PyCFuncPtr_FromDll
使用传递的kernel32 WinDLL对象从_handle
获取句柄对象,该对象将包含来自LoadLibrary
的地址,它将调用GetProcAddress
,最终< code >D29类型对象构造函数返回PyObject
用于从CDLL __getattr__
返回的函数指针实例。在其上执行的调用将导致python调用此对象中的地址,该地址将是GetProcAddress
,而不是解释字节码地址处的字节码的函数的地址。我现在无法验证细节,但对我来说,这就是我如何看到从Python运行时与windows API接口的可能性。
下一次不会调用__getattr__
,因为该属性现在存在。
https://stackoverflow.com/questions/17033733
复制相似问题