Windows 中 pwd.getpwnam(username).pw_dir 的等效项是什么?

发布于 2024-09-10 21:16:33 字数 346 浏览 3 评论 0原文

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

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

在 Windows 上可以可靠地获取此信息吗?如何?

The Python pwd module provides access to getpwnam(3) POSIX API, which can be used to get the home directory for a particular user by username, as well determining if the username is valid at all. pwd.getpwnam will raise an exception if called with a non-existent username.

At first it seems like the same result can be achieved in a cross-platform manner via os.path.expanduser('~username'). However, it appears that with Python 2.6 on Windows XP this won't actually produce a failure for a non-existent username. Furthermore, on Python 2.5 on Windows XP, it seems to fail even for valid users.

Can this information be obtained reliably on Windows? How?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

知足的幸福 2024-09-17 21:16:33

阅读 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]

Reading the 2.6 documentation shows that os.path.expanduser() is broken on Windows:

On Windows, HOME and USERPROFILE will
be used if set, otherwise a
combination of HOMEPATH and HOMEDRIVE
will be used. An initial ~user is
handled by stripping the last
directory component from the created
user path derived above.

Say whaat? This assumes all user homes have to be under the same parent directory. Nuh-ugh!

It was a bit hard to dig but here is a solution that will look up a local user by given name:

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]
南汐寒笙箫 2024-09-17 21:16:33

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

曾经有一个关于 Keith Brown .Net Windows 安全开发人员指南的不错的 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)

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

情况 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使用 python 的主目录?

I am new to Windows security... but reading MSDN and some blogs it seems to me that the way MS want us to handle other users specific data is by getting a user token.

There used to be a nice wiki of Keith Brown .Net Developers Guide to Windows Security... you can still find it in Google cache for "pluralsight keith.guidebook"

Case 1: If you don't have the user password:

For local accounts you can try reading the Windows registry as Nas Banov already suggested and there are some other recipes on SO or the Internet.

I am not sure how various Windows versions behaves for freshly create users ... those which have never performed an interactive session login ... does it automatically creates their registry, home folder and profile data?
I have done some tests on Windows XP and those registry keys were not present after creating an local account ... but in this case you can try to guess it based in All Users registry values ... or just fail :)

For desktop applications, when the application is running as a logged in user, I am using something like this to get the home folder.... and to get the equivalent of ~/.local I am using CSIDL_APPDATA, for roaming profiles, or just 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)

Reading Keith Brown article "How To Get A Token For A User" .. you can look for some other ways of getting an user token without a password...

Case 2: If you have the user password:

Reading the MSDN I got the impressing that if I have an user token, I can get its folders by calling something like the code below... but it did not worked for me. (not sure why)

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)

This is why I ended up with this code...which is far from being perfect due to the fact that it requires username and password.

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

This question is somehow related: How to find the real user home directory using python?

谜兔 2024-09-17 21:16:33

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

  import win32net

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

或者,您可以在 Windows 上扩展环境变量 USERPROFILE 或在 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

you could go the win32api.GetUserName() (current user only) or win32net.NetUserGetInfo() (any user on any server, localhost included) route. the latter could be a bit slow since it can take some time to get this information back from the OS.

  import win32net

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

alternatively you could expand the environment variable USERPROFILE on windows or HOME on unix to get the information about the currently logged in user:

  def userDir():
      if os.platform.system() == 'Windows':
          return os.environ['USERPROFILE']
      elif os.platform.system() == 'Linux':
          return os.environ['HOME'] 
      else:
          return None
何其悲哀 2024-09-17 21:16:33

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

This seems to be only applicable to the current user, but on my (winxp) machine, os.path.expanduser('~') returns my home directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文