#python #windows #api #ctypes
#python #Windows #API #ctypes
Вопрос:
Я пытаюсь перечислить каталог с помощью FindFirstFileW и FindNextFileW в python с использованием ctypes. 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)
Ответ №1:
Вы не установили .argtypes
и .restype
соответствующим образом для используемых функций. ctypes
предполагается, что возвращаемые значения являются c_int
, например, но дескрипторы являются 64-разрядными в 64-разрядном Python и усекаются до 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)