Windows 如何在PowerShell中找到用户envvars?

Windows 如何在PowerShell中找到用户envvars?,windows,powershell,Windows,Powershell,我明白了,可以在Windows PowerShell中点源脚本。如何取而代之地获取用户的环境变量(或者保存用户变量的文件路径) 示例1.ps1: [Environment]::SetEnvironmentVariable("PATH", "C:\newapp\bin", "User") newapp --do-something # fails until PS restart 环境变量存储在注册表中,而不是文件“”中,并且在PowerShell启动时自动加载。没有什么可供参考的。通过列出en

我明白了,可以在Windows PowerShell中点源脚本。如何取而代之地获取用户的环境变量(或者保存用户变量的文件路径)

示例1.ps1:

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

环境变量存储在注册表中,而不是文件“”中,并且在PowerShell启动时自动加载。没有什么可供参考的。通过列出
env:
PSDrive:

PS C:\> Get-ChildItem env: Name Value ---- ----- ALLUSERSPROFILE C:\ProgramData APPDATA C:\Users\jsmith\AppData\Roaming CommonProgramFiles C:\Program Files\Common Files ... 可以通过更改变量来修改当前环境

PS C:\> $env:Path += ';C:\some\folder' # append C:\some\folder to PATH 或者使用.NETAPI

[Environment]::SetEnvironmentVariable('foo', 'bar', 'User')
请注意,无法通过API更改注册表值

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

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

$env:foo = [Environment]::GetEnvironmentVariable('foo', 'User')
不过,请注意,Windows将用户和系统环境存储在不同的位置。如果您有一个在用户和系统环境中都定义的变量,如
$env:Path
,则需要组合这两个值:

$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' +
            [Environment]::GetEnvironmentVariable('Path', 'User')
如果需要为当前进程更改环境变量并将其持久化,则需要执行以下两个操作:更改
$env:variable
,并将更改后的变量写回注册表。如果需要多次执行此操作,建议将这两个操作包装到自定义函数中,例如:

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
}


从技术上讲,注册表中包含(除其他外)用户环境变量的部分存储在用户配置文件目录中的文件
ntuser.dat
中。然而,在PowerShell中,这是任何人都无法做到的。

您想要实现什么?环境变量在会话开始时加载,更改仅应用于“内存中”副本,通常在会话结束时丢弃。使用可以跨会话持久化更改。我正在尝试在脚本中设置用户$PATH,获取新的$PATH,然后稍后在同一ps1脚本中访问它,而无需退出PowerShell并重新运行设置
$env:PATH
应该做的事,除非您希望使更改持久化,在这种情况下,这将是的重复。只需同时执行这两个操作即可。设置
$env:PATH
会更改当前进程的路径,
Set ItemProperty
SetEnvironmentVariable()
会保留该值。在注册表中设置变量不会将其传播到当前进程,因此之后必须在当前进程中进行设置。你可能不喜欢它是这样工作的,但它仍然是这样工作的。(不幸的是,一厢情愿的想法并不会导致功能突然出现。)为什么不能点源ntuser.dat?因为它是一个二进制文件,包含注册表的用户配置单元。每个登录用户的
ntuser.dat
将加载到
HKU\
下的注册表中,并在
HKCU
下向相应用户显示。环境变量只是该文件的一小部分(您在
HKCU\Environment
下看到的内容)。这很有帮助,但不能回答问题。我需要设置持久的
$env:VAR
,然后在同一脚本中访问它,而无需重新启动PowerShell,一定有办法做到这一点吗?
$env:foo = [Environment]::GetEnvironmentVariable('foo', 'User')
$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' +
            [Environment]::GetEnvironmentVariable('Path', 'User')
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
}