2010-07-22 22 views
8

El módulo pwd de Python proporciona acceso a la API POSIX getpwnam(3), que se puede usar para obtener el directorio de inicio de un usuario en particular por nombre de usuario, y para determinar si el nombre de usuario es válido. pwd.getpwnam generará una excepción si se llama con un nombre de usuario inexistente.¿Cuál es el equivalente de Windows de pwd.getpwnam (username) .pw_dir?

Al principio parece que se puede obtener el mismo resultado de forma multiplataforma a través de os.path.expanduser('~username'). Sin embargo, parece que con Python 2.6 en Windows XP esto no producirá una falla para un nombre de usuario inexistente. Además, en Python 2.5 en Windows XP, parece fallar incluso para usuarios válidos.

¿Se puede obtener esta información de manera confiable en Windows? ¿Cómo?

+1

amor siempre una buena pregunta "Python en Windows". Cuanto antes traigamos la iluminación a esa plataforma (si es posible), mejor para todos. –

+0

'~ user' no debe funcionar en 2.5, está implementado en 2.6+ pero de una manera _broken_, vea mi respuesta a continuación para la implementación en funcionamiento. Sí, tuve que mirar en el registro, me temo. –

Respuesta

4

Lectura de la 2.6 documentation muestra que os.path.expanduser() se rompe en Windows:

En Windows, HOME y USERPROFILE se usará si está configurado, de lo contrario se usará una combinación de HOMEPATH y HOMEDRIVE . Un usuario inicial ~ es que se maneja al eliminar el último componente de directorio de la ruta de usuario creada anteriormente.

Diga whaat? Esto supone que todos los hogares de los usuarios deben estar bajo el mismo directorio principal. Nuh-ugh!

Fue un poco difícil de excavar, pero aquí es una solución que busque un usuario local por el nombre de pila:

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

esto produce resultados solo para usuarios locales? – akira

+0

solo para dejarlo en claro. – akira

+1

Este getUserDir parece prometedor. Probé mi problema, pero desafortunadamente me encontré con un problema donde mi código se ejecuta como un servicio que aparentemente no está asignado a un usuario (de alguna manera), por lo que una de las llamadas falló (con la excepción de que se quejaba de la falta de tal mapeo). Por el momento, me detuve allí, pero probablemente vuelva a visitar esto en algún momento. Quizás una vez que configure cualquier asignación que se requiera, esta función satisfará los requisitos. –

0

puede ir al win32api.GetUserName() (usuario actual solamente) o win32net.NetUserGetInfo() (cualquier usuario en cualquier servidor, localhost incluido) ruta. este último podría ser un poco lento, ya que puede llevar algo de tiempo recuperar esta información del sistema operativo.

import win32net 

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

, alternativamente, se podría ampliar la variable de entorno USERPROFILE en las ventanas o HOME en UNIX para obtener la información sobre el usuario actualmente conectado:

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

No funciona; esto arrojará información solo para el usuario * actual *. La pregunta es acerca de * any *, usuario 'particular'. –

+0

@Nas Banov: cierto, pero solo para la segunda parte de mi respuesta. win32api.NetUserGetInfo() recupera la información para CUALQUIER usuario. – akira

+0

@ Akira: Suena bien, pero ¿cómo? 'win32net.NetUserGetInfo (None, userName, 4))' devuelve ''home_dir': u''', es decir inútil –

0

Esto parece ser aplicable únicamente al usuario actual, pero en mi (WinXP) máquina, os.path.expanduser('~') devuelve mi directorio de inicio.

3

Soy nuevo en la seguridad de Windows ... pero leyendo MSDN y algunos blogs me parece que la forma en que MS quiere que manejemos datos específicos de otros usuarios es obteniendo un token de usuario.

No solía ser un buen wiki de Keith Brown Guía de desarrolladores de .NET para seguridad de Windows ... todavía se puede encontrar en Google caché para "Pluralsight keith.guidebook"

Caso 1: Si Don No tiene la contraseña de usuario:

Para las cuentas locales puede intentar leer el registro de Windows como ya sugirió Nas Banov y hay algunas otras recetas en SO o en Internet.

No estoy seguro de cómo se comportan varias versiones de Windows para usuarios recién creados ... aquellos que nunca han realizado un inicio de sesión de sesión interactivo ... ¿crea automáticamente su registro, carpeta de inicio y datos de perfil? He hecho algunas pruebas en Windows XP y esas claves de registro no estaban presentes después de crear una cuenta local ... pero en este caso puede intentar adivinarlo en base a los valores de registro de todos los usuarios ... o simplemente fallar :)

Para aplicaciones de escritorio, cuando la aplicación se ejecuta como un usuario conectado, estoy usando algo como esto para obtener la carpeta de inicio ... y para obtener el equivalente de ~/.local estoy usando CSIDL_APPDATA, para perfiles móviles , o solo 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) 

artículo de lectura Keith Brown "How To Get A Token For A User" .. se puede buscar algunas otras maneras de conseguir un token de usuario sin una contraseña ...

Caso 2: Si usted tiene la contraseña de usuario:

Lectura de MSDN Obtuve la impresión de que si tengo un token de usuario, puedo obtener sus carpetas llamando al código siguiente ... pero no funcionó. (No estoy seguro por qué)

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) 

Es por esto que terminó con el código ... que está lejos de ser perfecta debido al hecho de que requiere nombre de usuario y contraseña.

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() 

Esta pregunta tiene cierta relación: How to find the real user home directory using python?

Cuestiones relacionadas