8

Python pwd 模块提供对getpwnam(3)POSIX API 的访问,该 API 可用于通过用户名获取特定用户的主目录,以及确定用户名是否有效。 pwd.getpwnam如果使用不存在的用户名调用,将引发异常。

起初,似乎可以通过跨平台方式实现相同的结果os.path.expanduser('~username')。但是,对于 Windows XP 上的 Python 2.6,这似乎不会因为不存在的用户名而导致失败。此外,在 Windows XP 上的 Python 2.5 上,即使对于有效用户,它似乎也失败了。

能否在 Windows 上可靠地获取此信息?如何?

4

4 回答 4

4

阅读2.6 文档显示os.path.expanduser()在 Windows 上已损坏:

在 Windows 上,如果设置了 HOME 和 USERPROFILE,将使用,否则将使用 HOMEPATH 和 HOMEDRIVE 的组合。通过从上面派生的创建的用户路径中剥离最后一个目录组件来处理初始的~user 。

什么?这假设所有用户主目录都必须在同一个父目录下。唔—唔!

这有点难以挖掘,但这是一个通过给定名称查找本地用户的解决方案:

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]
于 2010-07-22T06:32:23.867 回答
3

我是 Windows 安全新手……但阅读 MSDN 和一些博客,在我看来,MS 希望我们处理其他用户特定数据的方式是获取用户令牌。

Keith Brown .Net Developers Guide to Windows Security 曾经有一个不错的 wiki……您仍然可以在 Google 缓存中找到它的“pluralsight keith.guidebook”

案例1:如果您没有用户密码:

对于本地帐户,您可以尝试按照 Nas Banov 的建议阅读 Windows 注册表,并且在 SO 或 Internet 上还有其他一些方法。

我不确定各种 Windows 版本对于新创建的用户的表现如何......那些从未执行过交互式会话登录的用户......它会自动创建他们的注册表、主文件夹和配置文件数据吗?我在 Windows XP 上做了一些测试,创建本地帐户后这些注册表项不存在...但在这种情况下,您可以尝试根据所有用户注册表值猜测它...或者只是失败:)

对于桌面应用程序,当应用程序以登录用户身份运行时,我正在使用类似的东西来获取主文件夹....并获得 ~/.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)

阅读 Keith Brown 文章“如何为用户获取令牌”.. 您可以寻找其他一些无需密码即可获取用户令牌的方法...

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

这个问题有点相关:How to find the real user home directory using python?

于 2011-03-05T11:02:47.447 回答
0

您可以走win32api.GetUserName()(仅限当前用户)或win32net.NetUserGetInfo()(任何服务器上的任何用户,包括本地主机)路线。后者可能有点慢,因为从操作系统获取这些信息可能需要一些时间。

  import win32net

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

USERPROFILE或者,您可以在 windows 或unix 上扩展环境变量HOME以获取有关当前登录用户的信息:

  def userDir():
      if os.platform.system() == 'Windows':
          return os.environ['USERPROFILE']
      elif os.platform.system() == 'Linux':
          return os.environ['HOME'] 
      else:
          return None
于 2010-07-22T04:46:22.790 回答
0

这似乎只适用于当前用户,但在我的(winxp)机器上,os.path.expanduser('~')返回我的主目录。

于 2010-07-22T13:07:28.460 回答