-1

我正在尝试使用 ctypes,但无法调用 FormatMessage() 正常工作。

这是我到目前为止的代码;我认为唯一的问题是传入一个可变缓冲区;我从 ctypes 收到关于 lpBuffer 的 ArgumentError

import ctypes
from ctypes.wintypes import DWORD

def main():
    fm = ctypes.windll.kernel32.FormatMessageA
    fm.argtypes = [DWORD,DWORD,DWORD,DWORD,ctypes.wintypes.LPWSTR(),DWORD]

    dwFlags = DWORD(0x1000) # FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM
    lpSource = DWORD(0)
    dwMessageId = DWORD(0x05)
    dwLanguageId = DWORD(0)
    #buf = ctypes.wintypes.LPWSTR()
    #lpBuffer = ctypes.byref(buf)
    lpBuffer = ctypes.create_string_buffer(512)
    nSize = DWORD(512)

    res = fm(dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize)
    print res

我在 lpBuffer 参数上收到一个错误,说它是错误的类型,但我已经尝试了尽可能多的传入缓冲区的变体。我尝试过类似于此处的操作:https : //gist.github.com/CBWhiz/6135237 并设置 FORMAT_MESSAGE_ALLOCATE_BUFFER 然后传入 LPWSTR() byref,我还尝试更改 argtype、指针和转换为各种LPWSTR()、c_char_p 等,但无论我做什么,它都在抱怨。

使函数正确执行的正确语法是什么?我知道 ctypes 可能很麻烦,但我在文档中没有找到任何解决问题的方法(我知道文档使用原型(),但我现在想这样做)

谢谢

4

1 回答 1

2

这是(注意Unicode的“W”)的argtypes定义:FormatMessageW

import ctypes
from ctypes import wintypes

fm = ctypes.windll.kernel32.FormatMessageW
fm.argtypes = [
    wintypes.DWORD,    # dwFlags
    wintypes.LPCVOID,  # lpSource
    wintypes.DWORD,    # dwMessageId
    wintypes.DWORD,    # dwLanguageId
    wintypes.LPWSTR,   # lpBuffer
    wintypes.DWORD,    # nSize
    wintypes.LPVOID,   # Arguments (va_list *)
]

FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100  
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000

如果FormatMessage分配缓冲区,则必须改为传递对lpBuffer. 只是cast参考绕过TypeError. 另外,记得调用kernel32.LocalFree释放缓冲区:

def main():
    dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
    lpSource = None
    dwMessageId = 5
    dwLanguageId = 0    
    lpBuffer = wintypes.LPWSTR()
    nSize = 0  # minimum size
    Arguments = None

    if not fm(dwFlags, lpSource, dwMessageId, dwLanguageId, 
              ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR), 
              nSize, Arguments):
        raise ctypes.WinError()

    msg = lpBuffer.value.rstrip()
    ctypes.windll.kernel32.LocalFree(lpBuffer)

    return msg
于 2013-09-20T00:20:52.263 回答