2011-11-10 10 views
6

के बिना पाइथन का उपयोग कर विंडोज़ पर फ़ाइल मालिक को कैसे निर्धारित करें मैं एक स्क्रिप्ट लिख रहा हूं जिसे विंडोज़ पर फ़ाइलों के मालिक का उपयोगकर्ता नाम निर्धारित करने की आवश्यकता है।pywin32

जबकि मुझे a solution using pywin32 मिला, लेकिन मुझे इसका उपयोग करने में संकोच नहीं है, क्योंकि मैं मॉड्यूल निर्भरता को जोड़ना नहीं चाहता हूं।

लिपि को पायथन 2.6 के लिए लिखा जाएगा और 32 बिट और 64 दोनों प्लेटफॉर्म पर चलना होगा।

अगर वहाँ एक अलग तरीका है, हो सकता है ctypes के साथ मैं सोच रहा था, यह जानकारी

उत्तर

11

निम्नलिखित ctypes का उपयोग करता GetNamedSecurityInfo कॉल करने के लिए। मूल रूप से यह code snippet का पालन करता है जो प्रश्न में जुड़ा हुआ है, लेकिन GetNamedSecurityInfoGetFileSecurity से सामान्य रूप से अधिक उपयोगी है, खासकर जब इसे अप्रचलित फ़ंक्शन SetFileSecurity के स्थान पर SetNamedSecurityInfo के साथ जोड़ा गया है।

ctypes और कक्षाओं

import ctypes as ctypes 
from ctypes import wintypes as wintypes 

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) 
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True) 

ERROR_INVALID_FUNCTION = 0x0001 
ERROR_FILE_NOT_FOUND = 0x0002 
ERROR_PATH_NOT_FOUND = 0x0003 
ERROR_ACCESS_DENIED  = 0x0005 
ERROR_SHARING_VIOLATION = 0x0020 

SE_FILE_OBJECT = 1 
OWNER_SECURITY_INFORMATION = 0x00000001 
GROUP_SECURITY_INFORMATION = 0x00000002 
DACL_SECURITY_INFORMATION = 0x00000004 
SACL_SECURITY_INFORMATION = 0x00000008 
LABEL_SECURITY_INFORMATION = 0x00000010 

_DEFAULT_SECURITY_INFORMATION = (OWNER_SECURITY_INFORMATION | 
    GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | 
    LABEL_SECURITY_INFORMATION) 

LPDWORD = ctypes.POINTER(wintypes.DWORD) 
SE_OBJECT_TYPE = wintypes.DWORD 
SECURITY_INFORMATION = wintypes.DWORD 

class SID_NAME_USE(wintypes.DWORD): 
    _sid_types = dict(enumerate(''' 
     User Group Domain Alias WellKnownGroup DeletedAccount 
     Invalid Unknown Computer Label'''.split(), 1)) 

    def __init__(self, value=None): 
     if value is not None: 
      if value not in self.sid_types: 
       raise ValueError('invalid SID type') 
      wintypes.DWORD.__init__(value) 

    def __str__(self): 
     if self.value not in self._sid_types: 
      raise ValueError('invalid SID type') 
     return self._sid_types[self.value] 

    def __repr__(self): 
     return 'SID_NAME_USE(%s)' % self.value 

PSID_NAME_USE = ctypes.POINTER(SID_NAME_USE) 

class PLOCAL(wintypes.LPVOID): 
    _needs_free = False 
    def __init__(self, value=None, needs_free=False): 
     super(PLOCAL, self).__init__(value) 
     self._needs_free = needs_free 

    def __del__(self): 
     if self and self._needs_free: 
      kernel32.LocalFree(self) 
      self._needs_free = False 

PACL = PLOCAL 

class PSID(PLOCAL): 
    def __init__(self, value=None, needs_free=False): 
     super(PSID, self).__init__(value, needs_free) 

    def __str__(self): 
     if not self: 
      raise ValueError('NULL pointer access') 
     sid = wintypes.LPWSTR() 
     advapi32.ConvertSidToStringSidW(self, ctypes.byref(sid)) 
     try: 
      return sid.value 
     finally: 
      if sid: 
       kernel32.LocalFree(sid) 

class PSECURITY_DESCRIPTOR(PLOCAL): 
    def __init__(self, value=None, needs_free=False): 
     super(PSECURITY_DESCRIPTOR, self).__init__(value, needs_free) 
     self.pOwner = PSID() 
     self.pGroup = PSID() 
     self.pDacl = PACL() 
     self.pSacl = PACL() 
     # back references to keep this object alive 
     self.pOwner._SD = self 
     self.pGroup._SD = self 
     self.pDacl._SD = self 
     self.pSacl._SD = self 

    def get_owner(self, system_name=None): 
     if not self or not self.pOwner: 
      raise ValueError('NULL pointer access') 
     return look_up_account_sid(self.pOwner, system_name) 

    def get_group(self, system_name=None): 
     if not self or not self.pGroup: 
      raise ValueError('NULL pointer access') 
     return look_up_account_sid(self.pGroup, system_name) 

def _check_bool(result, func, args): 
    if not result: 
     raise ctypes.WinError(ctypes.get_last_error()) 
    return args 

# msdn.microsoft.com/en-us/library/aa376399 
advapi32.ConvertSidToStringSidW.errcheck = _check_bool 
advapi32.ConvertSidToStringSidW.argtypes = (
    PSID, # _In_ Sid 
    ctypes.POINTER(wintypes.LPWSTR)) # _Out_ StringSid 

# msdn.microsoft.com/en-us/library/aa379166 
advapi32.LookupAccountSidW.errcheck = _check_bool 
advapi32.LookupAccountSidW.argtypes = (
    wintypes.LPCWSTR, # _In_opt_ lpSystemName 
    PSID,    # _In_  lpSid 
    wintypes.LPCWSTR, # _Out_opt_ lpName 
    LPDWORD,   # _Inout_ cchName 
    wintypes.LPCWSTR, # _Out_opt_ lpReferencedDomainName 
    LPDWORD,   # _Inout_ cchReferencedDomainName 
    PSID_NAME_USE) # _Out_  peUse 

# msdn.microsoft.com/en-us/library/aa446645 
advapi32.GetNamedSecurityInfoW.restype = wintypes.DWORD 
advapi32.GetNamedSecurityInfoW.argtypes = (
    wintypes.LPWSTR,  # _In_  pObjectName 
    SE_OBJECT_TYPE,  # _In_  ObjectType 
    SECURITY_INFORMATION, # _In_  SecurityInfo 
    ctypes.POINTER(PSID), # _Out_opt_ ppsidOwner 
    ctypes.POINTER(PSID), # _Out_opt_ ppsidGroup 
    ctypes.POINTER(PACL), # _Out_opt_ ppDacl 
    ctypes.POINTER(PACL), # _Out_opt_ ppSacl 
    ctypes.POINTER(PSECURITY_DESCRIPTOR)) # _Out_opt_ ppSecurityDescriptor 

कार्यों

def look_up_account_sid(sid, system_name=None): 
    SIZE = 256 
    name = ctypes.create_unicode_buffer(SIZE) 
    domain = ctypes.create_unicode_buffer(SIZE) 
    cch_name = wintypes.DWORD(SIZE) 
    cch_domain = wintypes.DWORD(SIZE) 
    sid_type = SID_NAME_USE() 
    advapi32.LookupAccountSidW(system_name, sid, name, ctypes.byref(cch_name), 
     domain, ctypes.byref(cch_domain), ctypes.byref(sid_type)) 
    return name.value, domain.value, sid_type 

def get_file_security(filename, request=_DEFAULT_SECURITY_INFORMATION): 
    # N.B. This query may fail with ERROR_INVALID_FUNCTION 
    # for some filesystems. 
    pSD = PSECURITY_DESCRIPTOR(needs_free=True) 
    error = advapi32.GetNamedSecurityInfoW(filename, SE_FILE_OBJECT, request, 
       ctypes.byref(pSD.pOwner), ctypes.byref(pSD.pGroup), 
       ctypes.byref(pSD.pDacl), ctypes.byref(pSD.pSacl), 
       ctypes.byref(pSD)) 
    if error != 0: 
     raise ctypes.WinError(error) 
    return pSD 

उदाहरण उपयोग

if __name__ == '__main__': 
    import os, sys 

    if len(sys.argv) < 2: 
     script_name = os.path.basename(__file__) 
     sys.exit('usage: {} filename'.format(script_name)) 

    filename = sys.argv[1] 
    if isinstance(filename, bytes): 
     if hasattr(os, 'fsdecode'): 
      filename = os.fsdecode(filename) 
     else: 
      filename = filename.decode(sys.getfilesystemencoding()) 

    pSD = get_file_security(filename) 
    owner_name, owner_domain, owner_sid_type = pSD.get_owner() 
    if owner_domain: 
     owner_name = '{}\\{}'.format(owner_domain, owner_name) 

    print("Path : {}".format(filename)) 
    print("Owner: {} ({})".format(owner_name, owner_sid_type)) 
    print("SID : {}".format(pSD.pOwner)) 

उदाहरण उत्पादन

Path : C:\Users 
Owner: NT AUTHORITY\SYSTEM (WellKnownGroup) 
SID : S-1-5-18 

Path : C:\ProgramData 
Owner: NT AUTHORITY\SYSTEM (WellKnownGroup) 
SID : S-1-5-18 

Path : C:\Program Files 
Owner: NT SERVICE\TrustedInstaller (WellKnownGroup) 
SID : S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 

Path : C:\Windows 
Owner: NT SERVICE\TrustedInstaller (WellKnownGroup) 
SID : S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 
+1

धन्यवाद जो मैं चाहता था। मैं केवल कुछ उपयोगकर्ताओं और समूहों को देखना चाहता हूं। मैं मानता हूं कि इस मुद्दे को हल करने का सबसे आसान तरीका नहीं है, लेकिन यह उप निर्भरता का उपयोग करके अतिरिक्त निर्भरताओं को रोकता है और बाहरी आदेशों को बुलाता है। इसके अलावा अब मुझे ctypes का उपयोग करके कुछ अभ्यास करने का वास्तविक कारण है। एमएसडीएन के संदर्भों के लिए भी बहुत धन्यवाद। – circus

+0

'sys.argv [1] 'एन्कोडिंग की संभावना है' locale.getpreferredencoding (झूठी)' /'sys.getfilesystemencoding() '(एएनएसआई सीपी),' sys.stdin.encoding' नहीं (OEM सीपी या जो भी 'сhcp' रिटर्न) - ऐसे कई रूपांतरण हैं जो डेटा खो सकते हैं ('sys.argv [1]' पहले ही दूषित हो सकता है)। यूनिकोड के रूप में फ़ाइल नाम प्राप्त करने के लिए: 'GetCommandLineW() '+' कमांडलाइन ToArgvW() ' – jfs

+0

@ जेएफ। सेबेस्टियन, धन्यवाद। मैंने इसे "एमबीसीएस" का उपयोग करने के लिए बदल दिया। मूल यूनिकोड कमांड लाइन प्राप्त करने के लिए आप 'win_unicode_console.enable (use_unicode_argv = True) का उपयोग भी कर सकते हैं, यदि आप पहले से ही पुराने पायथन संस्करणों के लिए कंसोल में यूनिकोड प्राप्त करने के लिए इसका उपयोग कर रहे हैं। – eryksun

3

निर्धारित करने के लिए आप एक विंडोज़ शेल कमांड "dir/q" नारा है और उत्पादन के मालिकों को खोजने के लिए पार्स सकता है।

subprocess.call("dir /q", shell=True) 
+0

यह ठीक से काम करने लगता है, लेकिन आप एकाधिक निर्देशिका यह बाह्य dir कमांड काफी एक बहुत कुछ कॉल करने के लिए की आवश्यकता होगी पर वितरित फ़ाइलों का एक बहुत कुछ के मालिक की जरूरत है जब। – circus

संबंधित मुद्दे