Python ctypes API调用导致访问冲突

2024-06-30 15:08:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用ctypes在python中列出一个包含FindFirstFileW和FindNextFileW的目录。FindFirstFileW成功,但FindNextFileW或FindClose导致操作错误:异常:访问冲突写入0xFFFFFFFFB8093F80

代码如下:

def assert_success(success):
    if not success:
        raise AssertionError(FormatError())

def assert_handle(handle):
    if handle == INVALID_HANDLE_VALUE:
        raise AssertionError(FormatError())
    

def FindFirstFileW(lpFileName):
    wfd = WIN32_FIND_DATAW()
    handle = windll.kernel32.FindFirstFileW(lpFileName, byref(wfd))
    assert_handle(handle)
    return handle, wfd

def FindNextFileW(handle):
    wfd = WIN32_FIND_DATAW()
    success = windll.kernel32.FindNextFileW(handle, byref(wfd))
    assert_success(success)
    return wfd

def FindClose(handle):
    success = windll.kernel32.FindClose(handle)
    assert_success(success)
    return success

handle, wfd = FindFirstFileW('C:\\Windows\\*')
print(wfd.cFileName)
wfd = FindNextFileW(handle)
print(wfd.cFileName)
FindClose(handle)

Tags: returnifdefassertsuccessraisehandleassertionerror
1条回答
网友
1楼 · 发布于 2024-06-30 15:08:39

您没有为正在使用的函数适当地设置.argtypes.restypectypes假设返回值是c_int,但在64位Python上句柄是64位的,并且被截断为32位。另外,由于ctypes知道参数类型应该是什么,因此您还可以通过类型检查调用获得额外的好处

还建议.errcheck自动检查返回值:

试试这个:

from ctypes import *
from ctypes import wintypes as w

INVALID_HANDLE_VALUE = w.HANDLE(-1).value
ERROR_NO_MORE_FILES = 18

def boolcheck(result,func,args):
    if not result:
        raise WinError(get_last_error())
    return None

# return True if more files
# return False if no more files
# raise exception for other reasons
def nomorecheck(result,func,args):
    if not result and get_last_error() != ERROR_NO_MORE_FILES:
        raise WinError(get_last_error())
    return result

def handlecheck(result,func,args):
    if result == INVALID_HANDLE_VALUE:
        raise WinError(get_last_error())
    return result

dll = WinDLL('kernel32',use_last_error=True)
dll.FindFirstFileW.argtypes = w.LPCWSTR,w.LPWIN32_FIND_DATAW
dll.FindFirstFileW.restype = w.HANDLE
dll.FindFirstFileW.errcheck = handlecheck
dll.FindNextFileW.argtypes = w.HANDLE,w.LPWIN32_FIND_DATAW
dll.FindNextFileW.restype = w.BOOL
dll.FindClose.errcheck = nomorecheck
dll.FindClose.argtypes = w.HANDLE,
dll.FindClose.restype = w.BOOL
dll.FindClose.errcheck = boolcheck

def find_files(directory):
    wfd = w.WIN32_FIND_DATAW()
    handle = dll.FindFirstFileW(directory, byref(wfd))
    yield wfd.cFileName
    while dll.FindNextFileW(handle, byref(wfd)):
        yield wfd.cFileName
    dll.FindClose(handle)

for file in find_files(r'c:\windows\*'):
    print(file)

相关问题 更多 >