您如何在 PowerShell 中获取用户环境变量? [英] How do you source User envvars in PowerShell?

查看:364
本文介绍了您如何在 PowerShell 中获取用户环境变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到 这里,它可以在 Windows PowerShell 中点源脚本.一个来源如何代替用户的环境变量(或保存用户变量的哪个文件路径)?

示例.ps1:

[Environment]::SetEnvironmentVariable("PATH", "C:\newapp\bin", "User")newapp --do-something # 失败直到 PS 重启

解决方案

环境变量存储在注册表中,而不是文件中¹,并且它们会在 PowerShell 启动时自动加载.没有什么可点源的.您可以通过列出env: PSDrive:

的内容来显示环境变量(用户环境与系统环境合并)<前>PS C:\> Get-ChildItem env:名称值---- -----ALLUSERSPROFILE C:\ProgramDataAPPDATA C:\Users\jsmith\AppData\RoamingCommonProgramFiles C:\Program Files\Common Files...

环境变量与常规 PowerShell 变量的不同之处在于它们必须通过 env 范围前缀访问:

<前>PS C:\> $username = 'foo' # ←PowerShell 变量PS C:\> $用户名富PS C:\> $env:username # ←环境变量史密斯

您可以通过更改变量来修改当前环境

<前>PS C:\> $env:Path += ';C:\some\folder' # 追加 C:\some\folder 到 PATH

或完全替换它们:

<前>PS C:\> $env:Path = 'C:\some\folder' # 设置路径为 C:\some\folder

不过,不建议操作像 $env:USERNAME 这样的环境变量.

但是请注意,虽然您可以修改环境变量或通过点源文件加载它们(在变量名称中使用适当的前缀),但这些变量在应用时不会持久化仅适用于流程环境.

要对环境变量进行持久更改,您需要编辑注册表中的值

Set-ItemProperty -Path 'HKCU:\Environment' -Name 'foo' -Value 'bar' -Type String

或使用 .Net API

[Environment]::SetEnvironmentVariable('foo', 'bar', 'User')

请注意,通过 API 更改注册表值存在陷阱.

使用 setx 命令行实用程序也可以使用,但我不建议这样做,因为语法并不像人们希望的那样简单,而且 PowerShell 一开始就不需要外部程序.

您还可以通过从注册表重新读取其值来更新在进程启动后更改的环境变量:

$env:foo = [Environment]::GetEnvironmentVariable('foo', 'User')

但是请注意,Windows 将用户和系统环境存储在不同的位置.如果您在用户和系统环境中都定义了像 $env:Path 这样的变量,您需要将这两个值结合起来:

$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';'+[环境]::GetEnvironmentVariable('Path', 'User')

如果您需要为当前进程更改环境变量并且持久化,您需要执行两个操作:更改 $env:VARIABLE 并将更改的变量写回注册表.如果您需要多次执行此操作,建议将这两个操作包装在自定义函数中,例如像这样:

function Set-EnvVariable {[CmdletBinding()]参数([参数(强制=$true)][字符串]$名称,[参数(强制=$true)]$价值,[参数(强制=$false)][字符串]$Type = '字符串')if (Test-Path -LiteralPath "env:$Name") {Set-Item "env:$Name" -Value $Value} 别的 {New-Item -Path 'env:' -Name $Name -Value $value}Set-ItemProperty -Path 'HKCU:\Environment' -Name $Name -Value $Value -Type $Type}

<小时>

¹ 好吧,从技术上讲,包含(除其他外)用户环境变量的注册表部分存储在用户配置文件目录中的 ntuser.dat 文件中.然而,这在 PowerShell 中是无法点源的.

I see here, its possible to dot source scripts in Windows PowerShell. How does one source the User's envvars instead (or which filepath are the User vars saved)?

Example.ps1:

[Environment]::SetEnvironmentVariable("PATH", "C:\newapp\bin", "User")
newapp --do-something # fails until PS restart

解决方案

Environment variables are stored in the registry, not in a file¹, and they're loaded automatically when PowerShell starts. There's nothing to dot-source. You can display environment variables (user environment merged with the system environment) by listing the content of the env: PSDrive:

PS C:\> Get-ChildItem env:

Name                           Value
----                           -----
ALLUSERSPROFILE                C:\ProgramData
APPDATA                        C:\Users\jsmith\AppData\Roaming
CommonProgramFiles             C:\Program Files\Common Files
...

Environment variables differ from regular PowerShell variables in that they must be accessed via the env scope prefix:

PS C:\> $username = 'foo'    # ← PowerShell variable
PS C:\> $username
foo
PS C:\> $env:username        # ← environment variable
jsmith

You can modify the current environment by making changes to the variables

PS C:\> $env:Path += ';C:\some\folder'    # append C:\some\folder to PATH

or replacing them entirely:

PS C:\> $env:Path = 'C:\some\folder'      # set PATH to C:\some\folder

It's not recommended to manipulate environment variables like $env:USERNAME, though.

Note, however, that while you can modify environment variables or load them by dot-sourcing a file (using the proper prefix in the variable names) these variables are not persisted as they're applied to the process environment only.

To make persistent changes to environment variables you need to edit the values in the registry

Set-ItemProperty -Path 'HKCU:\Environment' -Name 'foo' -Value 'bar' -Type String

or use the .Net API

[Environment]::SetEnvironmentVariable('foo', 'bar', 'User')

Beware that there are pitfalls to changing registry values via the API.

Using the setx commandline utility would also work, but I don't recommend that since the syntax is not as straightforward as one would like, and PowerShell doesn't need an external program in the first place.

You can also update an environment variable that was changed after the process was started by re-reading its value from the registry:

$env:foo = [Environment]::GetEnvironmentVariable('foo', 'User')

Beware, though, that Windows stores the user and system environment in different places. If you have a variable like $env:Path that is defined in both the user and the system environment you need to combine both values:

$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' +
            [Environment]::GetEnvironmentVariable('Path', 'User')

If you need an environment variable both changed for the current process and persisted you need to do both actions: change $env:VARIABLE and write the changed variable back to the registry. If you need to do this more than once, wrapping the two actions in a custom function might be advisable, e.g. like this:

function Set-EnvVariable {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [String]$Name,
        [Parameter(Mandatory=$true)]
        $Value,
        [Parameter(Mandatory=$false)]
        [String]$Type = 'String'
    )

    if (Test-Path -LiteralPath "env:$Name") {
        Set-Item "env:$Name" -Value $Value
    } else {
        New-Item -Path 'env:' -Name $Name -Value $value
    }

    Set-ItemProperty -Path 'HKCU:\Environment' -Name $Name -Value $Value -Type $Type
}


¹ Well, technically the part of the registry that contains (among other things) the user environment variables is stored in a file ntuser.dat in the user's profile directory. However, that's nothing one could dot-source in PowerShell.

这篇关于您如何在 PowerShell 中获取用户环境变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆