【问题标题】:Why would $env:username and [environment]::username return different users?为什么 $env:username 和 [environment]::username 会返回不同的用户?
【发布时间】:2019-10-25 20:24:37
【问题描述】:

PowerShell 的$env:username[environment]::username 有什么区别以及为什么它们可能会返回不同的用户? (我知道还有其他方法可以获取当前用户)

一些背景:

我有一个在发布目标上运行 PowerShell 脚本的 Azure 管道。管道代理配置为在特定服务帐户下运行。该 PowerShell 脚本的一部分使用 $env:username 分配权限。但是,权限被分配给本地管理员帐户。如果我将脚本更改为使用[environment]::username,则会为正确的服务帐户用户授予权限。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    $env: 正在查看您的环境变量。您正在查看的变量 - username- 默认情况下恰好设置为本地用户名。但不一定是这样。

    [Environment] 是对 .NET Framework 中的 System.Environment 类的调用。此类有一个名为 UserName 的属性,其中包含登录到计算机的用户名。

    相似的名字,但非常不同的东西。例如,您可以通过 $env:Path 获取路径语句,或者调用 [Environment]::Version 来获取 .NET Framework 的版本。

    请注意,在此示例中,我在启动 PowerShell 之前故意弄乱了本地环境变量以提供错误的用户名。

    C:\WINDOWS\system32>echo %username%
    mspow
    
    C:\WINDOWS\system32>set username=bob
    
    C:\WINDOWS\system32>echo %username%
    bob
    
    C:\WINDOWS\system32>powershell
    Windows PowerShell
    Copyright (C) Microsoft Corporation. All rights reserved.
    
    PS C:\WINDOWS\system32> echo $env:username
    bob
    PS C:\WINDOWS\system32> [Environment]::Username
    mspow
    PS C:\WINDOWS\system32> echo $env:ProgramFiles
    C:\Program Files
    PS C:\WINDOWS\system32> echo $env:path
    C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Users\mspow\AppData\Local\Microsoft\WindowsApps
    PS C:\WINDOWS\system32> [Environment]::Version
    
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    4      0      30319  42000
    

    您可以使用

    查看所有可用的环境变量
    Get-Item -Path Env:
    

    我知道查看 [Environment] 的所有方法和属性的唯一方法是指向 MSDN 站点的链接。 Get-Member 不起作用。

    【讨论】:

    • $env:USERNAME[Environment]::UserName 在技术上是不同的东西,但在概念上它们旨在包含相同的信息 - 虽然实际上你只能伪造前者,而不是后者。 [Environment] 是一个 static 类;如果您想查看其成员,请使用[Environment] | Get-Member -Static。顺便说一句:如果你想检查一个类型的 instance 成员,目前没有办法通过类型本身来做到这一点 - 你需要一个实例,这可能不是简单的构造 - 请参阅@ 987654322@.
    【解决方案2】:

    $env:USERNAME,而 predefined 反映当前用户的用户名,是一个 read-write 环境变量,就像任何其他环境变量一样。

    尽管这样做显然不可取,但 $env:USERNAME = 'foo' 之类的语句会更改当前进程及其子进程的环境变量 USERNAME 的值。

    这意味着如果环境变量USERNAME在同一会话或PowerShell的进程中被修改过,可能是通过明确指定的启动环境,它不再反映真实的用户名

    虽然我不知道为什么在 Azure Pipelines 的情况下 USERNAME 环境变量会与真实帐户不同,但在给定 @987654331 时,PowerShell 的 Start-Process cmdlet 设置了错误值的示例@ switch:由于 PowerShell Core 7.0.0-preview.5 / Windows PowerShell v5.1 的错误,$env:USERNAME 总是反映 SYSTEM,无论实际用户帐户如何 - 请参阅 this GitHub issue

    相比之下,[Environment]::UserName 使用不同的方法获取当前用户的用户名,它不依赖于$env:USERNAME 的值,始终反映真实的用户名[1]。 p>

    简而言之:只有[Environment]::UserName 可靠地反映了当前用户帐户的用户名。


    [1] 来自linked docs:“在 Windows 上,UserName 属性封装了对 Windows GetUserName 函数的调用。用户的域帐户凭据被格式化为用户的域名, \字符和用户名。使用UserDomainName属性获取用户的域名,使用UserName属性获取用户名。
    在 Unix 平台上,UserName 属性包含对 getpwuid_r 函数的调用。

    【讨论】:

    • 感谢您的详尽解释。对于那些感兴趣的人,自从我在管道日志中(在部署组作业初始化步骤)中确认了这个问题之后,username 环境变量被设置为本地管理员帐户。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    相关资源
    最近更新 更多