如何使用 ctypes 在 Python 中实现 NetUserGetInfo 函数
How to implement NetUserGetInfo function in Python using ctypes
我正在尝试使用 ctypes 在 python 中使用 NetUserGetInfo。
根据 documentation,该函数如下所示:
NET_API_STATUS NET_API_FUNCTION NetUserGetInfo(
LPCWSTR servername,
LPCWSTR username,
DWORD level,
LPBYTE *bufptr
);
我发现调用类型为 LPBYTE *bufptr
的函数的第四个参数有困难
我的代码如下所示:
import ctypes
from ctypes.wintypes import LPWSTR
netap = ctypes.WinDLL("Netapi32.dll")
servername = None
username = ctypes.c_wchar_p("myuser")
bufptr = ctypes.POINTER(ctypes.c_byte)
class USER_INFO_0(ctypes.Structure):
_fields_ = [
("usri0_name", LPWSTR)
]
usrio_name = username.bytes.decode()
level = USER_INFO_0()
response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
print(response)
出现以下错误:
Traceback (most recent call last):
File ".\netusertest.py", line 17, in <module>
response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCPointerType'
多多指教,初学者不用说!
这一行:
bufptr = ctypes.POINTER(ctypes.c_byte)
是一个类型声明,而不是一个实例,正如你的错误所指出的那样,所以它不能被引用。调用类型创建实例 (ctypes.POINTER(ctypes.c_byte))()
) 但我建议使用适当的 wintypes
代替。
我注意到您正在尝试初始化一个 USER_INFO_0
实例。这是由 API 分配和 return 编辑的,并且也必须被释放。 level
表示将 returned 的类型,因为它可以变化。
服务器名和用户名参数可以直接作为Unicode字符串传递。
它也有助于定义 .argtypes
和 .restype
以告知 ctypes
参数类型和 return 类型。不要 ctypes
猜测。如果定义正确ctypes
如果你传递一个不能转换为定义的类型将报错
这是在 32 位和 64 位 Python 上使用适当的 server/user 测试的代码:
import ctypes as ct
from ctypes import wintypes as w
# from lm.h headers.
NET_API_STATUS = w.DWORD
NERR_Success = 0
class USER_INFO_0(ct.Structure):
_fields_ = [('usri0_name', w.LPWSTR)]
# WinDLL is appropriate as NET_API_FUNCTION is defined as __stdcall.
# This matters if the code runs under 32-bit Python.
netap = ct.WinDLL('netapi32')
netap.NetUserGetInfo.argtypes = w.LPCWSTR, w.LPCWSTR, w.DWORD, ct.POINTER(w.LPBYTE)
netap.NetUserGetInfo.restype = NET_API_STATUS
netap.NetApiBufferFree.argtypes = w.LPVOID,
netap.NetApiBufferFree.restype = NET_API_STATUS
bufptr = w.LPBYTE() # make an LPBYTE instance to hold the output parameter.
level = 0
response = netap.NetUserGetInfo('server', 'account', level, ct.byref(bufptr))
if response == NERR_Success:
data = ct.cast(bufptr,ct.POINTER(USER_INFO_0)) # cast as indicated by level
print(data.contents.usri0_name) # dereference pointer and access member
netap.NetApiBufferFree(bufptr) # free the pointer
print(response)
我正在尝试使用 ctypes 在 python 中使用 NetUserGetInfo。
根据 documentation,该函数如下所示:
NET_API_STATUS NET_API_FUNCTION NetUserGetInfo(
LPCWSTR servername,
LPCWSTR username,
DWORD level,
LPBYTE *bufptr
);
我发现调用类型为 LPBYTE *bufptr
我的代码如下所示:
import ctypes
from ctypes.wintypes import LPWSTR
netap = ctypes.WinDLL("Netapi32.dll")
servername = None
username = ctypes.c_wchar_p("myuser")
bufptr = ctypes.POINTER(ctypes.c_byte)
class USER_INFO_0(ctypes.Structure):
_fields_ = [
("usri0_name", LPWSTR)
]
usrio_name = username.bytes.decode()
level = USER_INFO_0()
response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
print(response)
出现以下错误:
Traceback (most recent call last):
File ".\netusertest.py", line 17, in <module>
response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCPointerType'
多多指教,初学者不用说!
这一行:
bufptr = ctypes.POINTER(ctypes.c_byte)
是一个类型声明,而不是一个实例,正如你的错误所指出的那样,所以它不能被引用。调用类型创建实例 (ctypes.POINTER(ctypes.c_byte))()
) 但我建议使用适当的 wintypes
代替。
我注意到您正在尝试初始化一个 USER_INFO_0
实例。这是由 API 分配和 return 编辑的,并且也必须被释放。 level
表示将 returned 的类型,因为它可以变化。
服务器名和用户名参数可以直接作为Unicode字符串传递。
它也有助于定义 .argtypes
和 .restype
以告知 ctypes
参数类型和 return 类型。不要 ctypes
猜测。如果定义正确ctypes
如果你传递一个不能转换为定义的类型将报错
这是在 32 位和 64 位 Python 上使用适当的 server/user 测试的代码:
import ctypes as ct
from ctypes import wintypes as w
# from lm.h headers.
NET_API_STATUS = w.DWORD
NERR_Success = 0
class USER_INFO_0(ct.Structure):
_fields_ = [('usri0_name', w.LPWSTR)]
# WinDLL is appropriate as NET_API_FUNCTION is defined as __stdcall.
# This matters if the code runs under 32-bit Python.
netap = ct.WinDLL('netapi32')
netap.NetUserGetInfo.argtypes = w.LPCWSTR, w.LPCWSTR, w.DWORD, ct.POINTER(w.LPBYTE)
netap.NetUserGetInfo.restype = NET_API_STATUS
netap.NetApiBufferFree.argtypes = w.LPVOID,
netap.NetApiBufferFree.restype = NET_API_STATUS
bufptr = w.LPBYTE() # make an LPBYTE instance to hold the output parameter.
level = 0
response = netap.NetUserGetInfo('server', 'account', level, ct.byref(bufptr))
if response == NERR_Success:
data = ct.cast(bufptr,ct.POINTER(USER_INFO_0)) # cast as indicated by level
print(data.contents.usri0_name) # dereference pointer and access member
netap.NetApiBufferFree(bufptr) # free the pointer
print(response)