Что такое Windows-эквивалент pwd.getpwnam (имя пользователя) .pw_dir? - PullRequest
8 голосов
/ 22 июля 2010

Модуль Python pwd предоставляет доступ к getpwnam(3) POSIX API, который можно использовать для получения домашнего каталога для конкретного пользователя по имени пользователя, а также для определения, является ли имя пользователя действительным вообще. pwd.getpwnam вызовет исключение при вызове с несуществующим именем пользователя.

Сначала кажется, что тот же результат может быть достигнут кросс-платформенным способом через os.path.expanduser('~username'). Однако, похоже, что в Python 2.6 в Windows XP это фактически не приведет к сбою для несуществующего имени пользователя. Кроме того, в Python 2.5 в Windows XP он, похоже, не работает даже для действительных пользователей.

Может ли эта информация быть надежно получена в Windows? Как?

Ответы [ 4 ]

4 голосов
/ 22 июля 2010

Чтение документации 2.6 показывает, что os.path.expanduser() не работает в Windows:

В Windows будут использоваться HOME и USERPROFILE, если установлены, в противном случае комбинация HOMEPATH иHOMEDRIVE будет использоваться.Начальный ~ пользователь обрабатывается путем удаления последнего компонента каталога из созданного выше пути пользователя.

Скажем что ?Это предполагает, что все домашние пользователи должны находиться в одном родительском каталоге.Нее-тьфу!

Было немного сложно копать, но вот решение, которое будет искать локального пользователя по имени:

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]
3 голосов
/ 05 марта 2011

Я новичок в безопасности Windows ... но, читая MSDN и некоторые блоги, мне кажется, что MS хочет, чтобы мы обрабатывали данные других пользователей, путем получения токена пользователя.

будьте хорошей вики из Руководства для разработчиков по безопасности Windows Keith Brown .Net ... вы все равно можете найти его в кэше Google для "pluralsight keith.guidebook"

Случай 1: если у вас нетпароль пользователя:

Для локальных учетных записей вы можете попробовать прочитать реестр Windows, как уже предложил Нас Банов, и есть несколько других рецептов на SO или в Интернете.

Я не уверенкак ведут себя различные версии Windows для только что созданных пользователей ... тех, которые никогда не выполняли интерактивную регистрацию в сеансе ... автоматически ли он создает реестр, домашнюю папку и данные профиля?Я провел несколько тестов на Windows XP, и эти разделы реестра отсутствовали после создания локальной учетной записи ... но в этом случае вы можете попытаться угадать его на основе значений реестра All Users ... или просто не сработать :)

Для настольных приложений, когда приложение работает как зарегистрированный пользователь, я использую что-то вроде этого, чтобы получить домашнюю папку .... и получить эквивалент ~ / .local. Я использую CSIDL_APPDATA для роуминга.профили или просто 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)

Чтение статьи Кейта Брауна " Как получить токен для пользователя " .. Вы можете найти другие способы получения токена пользователя безпароль ...

Случай 2: Если у вас есть пароль пользователя:

При чтении MSDN у меня сложилось впечатление, что если у меня есть токен пользователя, я могуполучить его папки, вызвав что-то вроде кода ниже ... но это не сработало для меня.(не знаю почему)

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)

Вот почему я получил этот код ... который далек от совершенства из-за того, что для него требуются имя пользователя и пароль.

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

Этот вопрос как-то связан: Как найти домашний каталог реального пользователя с помощью python?

0 голосов
/ 22 июля 2010

Похоже, что это применимо только к текущему пользователю, но на моем (winxp) компьютере os.path.expanduser('~') возвращает мой домашний каталог.

0 голосов
/ 22 июля 2010

Вы можете пойти по маршруту win32api.GetUserName() (только для текущего пользователя) или win32net.NetUserGetInfo() (любой пользователь на любом сервере, включая localhost).последний может быть немного медленным, поскольку может потребоваться некоторое время, чтобы получить эту информацию из ОС.

  import win32net

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

в качестве альтернативы вы можете расширить переменную окружения USERPROFILE в Windows или HOME в Unix дополучить информацию о текущем вошедшем в систему пользователе:

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