2010-07-22 5 views
8

Das Python-Modul pwd ermöglicht den Zugriff auf die POSIX-API , die verwendet werden kann, um das Basisverzeichnis für einen bestimmten Benutzer nach Benutzername zu ermitteln und festzustellen, ob der Benutzername überhaupt gültig ist. pwd.getpwnam löst eine Ausnahme aus, wenn sie mit einem nicht vorhandenen Benutzernamen aufgerufen wird.Was ist das Windows-Äquivalent von pwd.getpwnam (Benutzername) .pw_dir?

Zunächst scheint es, als ob das selbe Ergebnis plattformübergreifend über os.path.expanduser('~username') erreicht werden kann. Es scheint jedoch, dass dies mit Python 2.6 unter Windows XP nicht zu einem Fehler für einen nicht existierenden Benutzernamen führt. Außerdem scheint es auf Python 2.5 unter Windows XP sogar für gültige Benutzer nicht zu funktionieren.

Können diese Informationen unter Windows zuverlässig abgerufen werden? Wie?

+1

immer eine gute "Python unter Windows" Frage liebt. Je früher wir die Erleuchtung auf diese Plattform bringen (wenn es möglich ist), desto besser für alle. –

+0

'~ Benutzer' soll nicht auf 2.5 arbeiten, es ist in 2.6+ implementiert, aber auf eine gebrochene Weise - siehe meine Antwort unten für die Arbeitsimplementierung. Ja, ich musste in der Registry gucken, fürchte ich. –

Antwort

4

Lesen der 2.6 documentation zeigt, dass os.path.expanduser() auf Windows gebrochen wird:

Unter Windows HOME und USERPROFILE wird verwendet werden falls eingestellt, wird andernfalls eine Kombination von HOMEPATH und HOMEDRIVE verwendet. Eine anfängliche ~ Benutzer ist behandelt durch Abisolieren der letzten Verzeichniskomponente aus dem oben abgeleiteten Benutzerpfad erstellt.

Say whaat? Dies setzt voraus, dass sich alle Benutzerhomes im selben übergeordneten Verzeichnis befinden müssen. Nuh-ugh!

Es war ein bisschen schwer zu graben, aber hier ist eine Lösung, die von bestimmten Namen einen lokalen Benutzer nachschlägt:

from win32security import LookupAccountName, ConvertSidToStringSid 
from _winreg import OpenKey, QueryValueEx, HKEY_LOCAL_MACHINE 

def getUserDir(userName): 
    ssid = ConvertSidToStringSid(LookupAccountName(None, userName)[0]) 
    key = OpenKey(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\\' + ssid) 
    return QueryValueEx(key, 'ProfileImagePath')[0] 
+1

Dies führt zu Ergebnissen nur für lokale Benutzer? – akira

+0

nur um es klar zu machen. – akira

+1

Dieses getUserDir sieht vielversprechend aus. Ich habe es mit meinem Problem ausprobiert, bin aber leider sofort auf ein Problem gestoßen, bei dem mein Code als Dienst läuft, der anscheinend keinem Benutzer zugeordnet ist (irgendwie), so dass einer der Anrufe fehlgeschlagen ist (mit einer Ausnahme, die sich über das Fehlen von solch eine Abbildung). Vorläufig habe ich dort angehalten, aber wahrscheinlich werde ich das irgendwann wieder besuchen. Vielleicht sobald ich das Mapping eingerichtet habe, wird diese Funktion die Anforderungen erfüllen. –

0

können Sie die win32api.GetUserName() (aktueller Benutzer) oder win32net.NetUserGetInfo() (beliebiger Benutzer auf jedem Server, localhost enthalten) gehen. Letzteres könnte etwas langsam sein, da es einige Zeit dauern kann, bis diese Informationen vom Betriebssystem abgerufen werden.

import win32net 

    def userDir(username): 
     return win32net.NetUserGetInfo(None, username, 1).get("home_dir") 

alternativ können Sie die Umgebungsvariable USERPROFILE auf Windows oder HOME auf Unix erweitern, um die Informationen über die aktuell angemeldeten Benutzers zu erhalten:

def userDir(): 
     if os.platform.system() == 'Windows': 
      return os.environ['USERPROFILE'] 
     elif os.platform.system() == 'Linux': 
      return os.environ['HOME'] 
     else: 
      return None 
+0

Funktioniert nicht - dies gibt Informationen nur für den * aktuellen * Benutzer zurück. Die Frage bezieht sich auf * jeden *, 'bestimmten' Benutzer. –

+0

@Nas Banov: stimmt, aber nur für den zweiten Teil meiner Antwort. win32api.NetUserGetInfo() ruft die Informationen für ANY-Benutzer ab. – akira

+0

@Akira: Klingt gut, aber wie? 'win32net.NetUserGetInfo (None, userName, 4))' gibt '' home_dir 'zurück: u''', also nutzlos –

0

Dies scheint auf den aktuellen Benutzer nur anwendbar zu sein, aber für mich (winxp) Maschine, os.path.expanduser('~') gibt mein Home-Verzeichnis zurück.

3

Ich bin neu in der Windows-Sicherheit ... aber beim Lesen von MSDN und einigen Blogs scheint mir, dass die Art und Weise, wie MS mit anderen benutzerspezifischen Daten umgehen soll, ein Benutzer-Token ist.

Es verwendet ein schönes Wiki von Keith Brown .Net Developers Guide zu Windows-Sicherheit zu sein ... Sie es immer noch im Google-Cache für "Plural keith.guidebook"

Fall 1 finden: Wenn Sie don Habe kein Benutzerpasswort:

Für lokale Konten können Sie versuchen, die Windows-Registrierung zu lesen, wie Nas Banov bereits vorgeschlagen hat, und es gibt einige andere Rezepte auf SO oder im Internet.

Ich bin nicht sicher, wie verschiedene Windows-Versionen sich für neu erstellte Benutzer verhalten ... diejenigen, die noch nie eine interaktive Sitzung Anmeldung durchgeführt haben ... erstellt sie automatisch ihre Registrierung, Home-Ordner und Profildaten? Ich habe einige Tests auf Windows XP durchgeführt und diese Registrierungsschlüssel waren nicht vorhanden nach dem Erstellen eines lokalen Kontos ... aber in diesem Fall können Sie versuchen, es in All Users Registry-Werte zu erraten ... oder einfach scheitern :)

Für Desktop-Anwendungen, wenn die Anwendung als angemeldeter Benutzer ausgeführt wird, verwende ich so etwas, um den Home-Ordner zu erhalten .... und um das Äquivalent von ~/.local zu erhalten, verwende ich CSIDL_APPDATA für Roaming-Profile oder nur CSIDL_LOCAL_APPDATA.

from win32com.shell import shell, shellcon 
# See microsoft references for further CSIDL constants 
# http://msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, 0, 0) 

Lesen Keith Brown Artikel „How To Get A Token For A User“ .. Sie für einige andere Wege, um ein Benutzertoken, ohne ein Passwort aussehen kann ...

Fall 2: Wenn Sie das Benutzerkennwort:

Das Lesen der MSDN Ich habe das Beeindruckende, dass ich, wenn ich ein Benutzer-Token habe, seine Ordner abrufen kann, indem ich etwas wie den Code unten anrufe ... aber es hat nicht für mich funktioniert. (Nicht sicher, warum)

token = win32security.LogonUser(
      username, 
      None, # we uses UPN format for username 
      password, 
      win32security.LOGON32_LOGON_NETWORK, 
      win32security.LOGON32_PROVIDER_DEFAULT, 
      ) 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, token, 0) 

diesem Grund habe ich mit diesem Code am Ende ..., die weit davon entfernt ist, perfekt zu sein aufgrund der Tatsache, dass es Benutzernamen und ein Passwort erfordert.

token = win32security.LogonUser(
      username, 
      None, # Here should be the domain ... or just go with default values 
      password, 
      win32security.LOGON32_LOGON_NETWORK, 
      win32security.LOGON32_PROVIDER_DEFAULT, 
      ) 
win32security.ImpersonateLoggedOnUser(token) 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, 0, 0) 
win32security.RevertToSelf() 

Diese Frage ist irgendwie miteinander verwandt: How to find the real user home directory using python?