Pergunta

O módulo Python pwd fornece acesso a getpwnam(3) API POSIX, que pode ser usada para obter o diretório inicial de um usuário específico por nome de usuário, bem como determinar se o nome de usuário é válido. pwd.getpwnam gerará uma exceção se for chamado com um nome de usuário inexistente.

À primeira vista, parece que o mesmo resultado pode ser alcançado de maneira multiplataforma via os.path.expanduser('~username').No entanto, parece que com o Python 2.6 no Windows XP isso não produzirá uma falha para um nome de usuário inexistente.Além disso, no Python 2.5 no Windows XP, parece falhar mesmo para usuários válidos.

Essas informações podem ser obtidas de forma confiável no Windows?Como?

Foi útil?

Solução

Lendo o 2.6 documentação mostra que os.path.expanduser() está quebrado no Windows:

No Windows, Home e UserProfile serão usados ​​se estiver definido, caso contrário, será usada uma combinação de patrimão e homedrive HOMEDRIVE.Uma inicial ~usuário é tratado removendo o último componente de diretório do caminho do usuário criado derivado acima.

Dizer o que?Isso pressupõe que todas as casas dos usuários devem estar no mesmo diretório pai.Não!

Foi um pouco difícil de cavar, mas aqui está uma solução que irá procurar um usuário local pelo nome:

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]

Outras dicas

Eu sou novo na segurança do Windows ...mas lendo o MSDN e alguns blogs, parece-me que a maneira como a MS deseja que tratemos os dados específicos de outros usuários é obtendo um token de usuário.

Costumava haver um bom wiki de Keith Brown .Net Developers Guide to Windows Security ...você ainda pode encontrá-lo no cache do Google para "pluralsight keith.guidebook"

Caso 1:Se você não tiver a senha do usuário:

Para contas locais você pode tentar ler o registro do Windows como Nas Banov já sugeriu e existem algumas outras receitas no SO ou na Internet.

Não tenho certeza de como as várias versões do Windows se comportam para usuários recém-criados...aqueles que nunca realizaram um login de sessão interativa...ele cria automaticamente seu registro, pasta pessoal e dados de perfil?Fiz alguns testes no Windows XP e essas chaves de registro não estavam presentes após a criação de uma conta local...mas neste caso você pode tentar adivinhar com base nos valores de registro de Todos os Usuários ...ou simplesmente falhar :)

Para aplicativos de desktop, quando o aplicativo está sendo executado como um usuário logado, estou usando algo assim para obter a pasta inicial....e para obter o equivalente a ~/.local estou usando CSIDL_APPDATA, para perfis móveis, ou apenas 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)

Lendo o artigo de Keith Brown "Como obter um token para um usuário" ..você pode procurar outras maneiras de obter um token de usuário sem senha ...

Caso 2:Se você tiver a senha do usuário:

Lendo o MSDN tive a impressão de que se eu tiver um token de usuário, posso obter suas pastas chamando algo como o código abaixo...mas não funcionou para mim.(não sei por que)

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)

Por isso acabei com esse código... que está longe de ser perfeito por exigir nome de usuário e senha.

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 questão está de alguma forma relacionada: Como encontrar o diretório inicial do usuário real usando python?

você poderia ir win32api.GetUserName() (somente usuário atual) ou win32net.NetUserGetInfo() (qualquer usuário em qualquer servidor, incluindo localhost).o último pode ser um pouco lento, pois pode levar algum tempo para recuperar essas informações do sistema operacional.

  import win32net

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

alternativamente, você pode expandir a variável de ambiente USERPROFILE nas janelas ou HOME no unix para obter as informações sobre o usuário conectado no momento:

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

Isso parece ser aplicável apenas ao usuário atual, mas na minha máquina (winxp), os.path.expanduser('~') retorna meu diretório inicial.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top