我在使用Python调用GetModuleHandleA()
时遇到问题。我有一个模块作为调试器附加到进程。我正在开发一个函数,它将返回特定DLL模块中函数的地址。 GetModuleHandleA("msvcr100")
一直都失败了。
from ctypes import *
kernel32 = windll.kernel32
声明为较大的 debug 类的一部分的函数。这是函数声明的一部分:
def resolve_function(self,dll,function):
handle = kernel32.GetModuleHandleA(dll)
if handle == False:
print "kernel32.GetModuleNameA() failed!!!"
return False
address = kernel32.GetProcAddress(handle, function)
if address == False:
print "kernel32.GetProcAddress() failed!!!"
return False
kernel32.CloseHandle(handle)
return address
将函数调用为:
function_address = debug.resolve_function("msvcr100", "printf")
我运行使用printf()的单独进程然后附加到它。一切正常,直到我到达GetModuleHandleA(),一直返回 False 。
运行printf()的代码:
from ctypes import *
import time
msvcr100 = cdll.msvcr100
counter = 0
while 1:
msvcr100.printf("Counter = %d\n" % counter)
time.sleep(1)
counter += 1
有什么想法吗?
答案 0 :(得分:5)
You've found the solution你的问题,但无论如何我都要回答你原来的努力失败的原因(以及为什么你的修复有效)。
首先,msvcrt / msvcr100是Microsoft的C运行时库的两个不同版本。还有其他版本,所有版本都包含自己的printf()
定义。给定的进程可能已加载其中任何一个,或加载了多个版本,或加载了 no 版本 - 可以生成控制台输出using only WinAPI functions!简而言之,如果它不是您的过程,则您不能依赖任何给定版本的C运行时可用。
其次, GetModuleHandle()
不加载任何。只有当已加载时,它才会返回指定模块的句柄。 msvcr100.dll可以在磁盘上就位,但如果进程尚未加载,则GetModuleHandle将不会为您提供句柄。如果你想加载和检索指定模块的句柄,那么LoadLibrary()
就是你要调用的函数......但你可能不想要在你不拥有的过程中这样做。
FWIW,Process Explorer是查看进程已加载的DLL的便捷工具。
答案 1 :(得分:1)
修改后:
...
handle = kernel32.GetModuleHandleA(dll)
if handle == False:
error = GetLastError()
print "ERROR: %d - %s" % (error, FormatError(error))
return False
...
我得到:错误:126 - 找不到指定的模块
我实际上在我的代码中用msvcrt.dll替换了msvcr100.dll,它完美无缺。我发现msvcrt.dll是系统dll。 msvcr100.dll随Studio 2010一起提供。它们都位于C:\ Windows \ system32中。对我来说,为什么msvcr100.dll不起作用仍然是个谜。
答案 2 :(得分:0)
使用GetLastError()
中的WinError
(或ctypes
)来查找返回NULL的原因,然后将该信息添加到错误消息中。即使在你弄清楚这个特定问题之后,你也会想要更强大的错误报告。
有关详细信息,请参阅ctypes文档:http://docs.python.org/library/ctypes.html
答案 3 :(得分:0)
尝试致电:
msvcr100 = cdll.msvcr100
致电之前:
function_address = debug.resolve_function("msvcr100", "printf")
确保在您的进程中加载DLL。 msvcrt
可能有效,因为它已经加载了。