我正在尝试使用 ctypes 获取文件所有者信息(域名和用户名)。在 python 中,我使用 os.walk 来获取文件列表。
for root, dirs, files in os.walk("c:\\"):
for file in files:
filename = os.path.join(root, file)
owner = PL_Files.get_fileowner(filename)
print(owner)
要获取“PL_Files.get_fileowner”中的所有者信息,我使用 GetNamedSecurityInfoW。它运行良好(它返回域名和用户名)。
@staticmethod
def get_fileowner(filename):
dwRet = 0
pSidOwner = c_void_p()
ppSecurityDescriptor = c_void_p()
dwAcctName = DWORD()
dwDomainName = DWORD()
peUse = DWORD(SidTypeUnknown)
dwRet = GetNamedSecurityInfoW(filename, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, byref(pSidOwner), None, None, None, None)
if dwRet != ERROR_SUCCESS:
return "-1"
LookupAccountSidW(None, pSidOwner, None, byref(dwAcctName), None, byref(dwDomainName), byref(peUse))
AcctName = create_unicode_buffer(dwAcctName.value + 2)
DomainName = create_unicode_buffer(dwDomainName.value + 2)
if LookupAccountSidW(None, pSidOwner, AcctName, byref(dwAcctName), DomainName, byref(dwDomainName), byref(peUse)):
return "{}\{}".format(DomainName.value, AcctName.value)
else:
return "-1"
问题是每次调用 PL_Files.get_fileowner(filename) 我的进程内存都会增加约 2MB。
当我评论(没有调用)LookupAccountSidW 函数时,结果相同。所以我认为 GetNamedSecurityInfoW 函数有问题。 GetNamedSecurityInfoW 不需要释放内存(如果您不使用 ppSecurityDescriptor)。
函数原型:
GetNamedSecurityInfoW = ADVAPI32.GetNamedSecurityInfoW
GetNamedSecurityInfoW.restype = DWORD
GetNamedSecurityInfoW.argtypes = [c_wchar_p, INT, DWORD, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p]
使用CTypes时需要注意:
[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案) 常见的陷阱
每个功能的文档(并按照其中的指示进行操作)
但是对于这种情况,值得一提的是 [GitHub]:mhammond/pywin32 - Python for Windows (pywin32) Extensions,它是 WinAPI 的 Python 包装器。文档 (WiP) 可以在 [GitHub.MHammond]: Python for Win32 Extensions Help(或 [ME.TimGolden]: Python for Win32 Extensions Help)找到,因为问题也被标记为。
这是利用它的替代实现。
code00.py:
#!/usr/bin/env python
import os
import sys
import pywintypes as pwts
import win32security as wsec
def fileowner_pywin32(file_name):
try:
sec_desc = wsec.GetNamedSecurityInfo(file_name, wsec.SE_FILE_OBJECT, wsec.OWNER_SECURITY_INFORMATION)
except pwts.error as e:
#print(e)
return None
else:
owner_sid = sec_desc.GetSecurityDescriptorOwner()
#print(owner_sid)
try:
name, domain, _ = wsec.LookupAccountSid(None, owner_sid)
except pwts.error as e:
#print(e)
return None
else:
return f"{domain}\\{name}"
def main(*argv):
test_dir = argv[0] if argv else os.getcwd()
max_files = int(argv[1]) if len(argv) >= 2 and argv[1].isdigit() else 10
print(f"Display file (max: {max_files}) information for: {test_dir}")
total_files = 0
for root, dirs, files in os.walk(test_dir):
for file in files:
#print(root, file)
file_full = os.path.join(root, file)
owner = fileowner_pywin32(file_full)
print(f"{file_full}: {owner}")
total_files += 1
if max_files > 0 and total_files >= max_files:
return
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
输出:
[cfati@CFATI-W10PC064:e:\Work\Dev\StackExchange\StackOverflow\q077878192]> "c:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./code00.py "c:" 20 Python 3.10.10 (tags/v3.10.10:aad5f6a, Feb 7 2023, 17:20:36) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Display file (max: 20) information for: c: c:DumpStack.log: BUILTIN\Administrators c:DumpStack.log.tmp: None c:pagefile.sys: None c:swapfile.sys: None c:$GetCurrent\Logs\downlevel_2021_05_15_23_18_17_211.log: BUILTIN\Administrators c:$GetCurrent\Logs\oobe_2021_05_16_04_23_10_420.log: NT AUTHORITY\SYSTEM c:$GetCurrent\Logs\PartnerSetupCompleteResult.log: NT AUTHORITY\SYSTEM c:$GetCurrent\SafeOS\GetCurrentOOBE.dll: BUILTIN\Administrators c:$GetCurrent\SafeOS\GetCurrentRollback.ini: BUILTIN\Administrators c:$GetCurrent\SafeOS\PartnerSetupComplete.cmd: BUILTIN\Administrators c:$GetCurrent\SafeOS\preoobe.cmd: BUILTIN\Administrators c:$GetCurrent\SafeOS\SetupComplete.cmd: BUILTIN\Administrators c:$Recycle.Bin\S-1-5-18\desktop.ini: BUILTIN\Administrators c:$Recycle.Bin\S-1-5-21-2542118664-3911450730-4233525012-1000\desktop.ini: None c:$Recycle.Bin\S-1-5-21-2542118664-3911450730-4233525012-1001\desktop.ini: CFATI-W10PC064\cfati c:Download\EnergyPlus-22.2.0-c249759bad-Windows-i386.zip: BUILTIN\Administrators c:Download\strawberry-perl-5.32.1.1-64bit.msi: BUILTIN\Administrators c:Install\MS\SysInternalsSuite\Version\accesschk.exe: BUILTIN\Administrators c:Install\MS\SysInternalsSuite\Version\accesschk64.exe: BUILTIN\Administrators c:Install\MS\SysInternalsSuite\Version\AccessEnum.exe: BUILTIN\Administrators Done.