-1

ctypes を使用しようとしていますが、FormatMessage() の呼び出しが正しく機能しません。

これが私がこれまでに持っているコードです。唯一の問題は、可変バッファを渡すことだと思います。lpBuffer について ctypes から 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が巧妙である可能性があることを知っていますが、問題を解決するためのドキュメントには何も見つかりませんでした(ドキュメントがprototype()を使用していることは知っていますが、今のところこの方法でやりたいです)

ありがとう

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するための参照のみTypeErrorkernel32.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 に答える