如果 PowerShell 中的环境变量不存在,如何设置它?

Posted

技术标签:

【中文标题】如果 PowerShell 中的环境变量不存在,如何设置它?【英文标题】:How do I set an env variable in PowerShell if it doesn't exist? 【发布时间】:2016-12-20 01:55:52 【问题描述】:

我很惊讶在谷歌搜索了一段时间后我没有得到这个常见场景的答案......

如果环境变量不存在,如何在PowerShell中设置?

【问题讨论】:

【参考方案1】:

以下代码为当前进程定义环境变量FOO,如果它还不存在的话。

if ($null -eq $env:FOO)  $env:FOO = 'bar' 

# Alternatively:
if (-not (Test-Path env:FOO))  $env:FOO = 'bar' 

在具有null-coalescing operators的PowerShell (Core) 7.1+中,您可以简化为:

$env:FOO ??= 'bar'

注意:根据定义,环境变量是字符串。如果给定环境变量定义,但没有值,它的值是空字符串 ('') 而不是$null .因此,与$null 比较可用于区分未定义 环境变量和已定义但没有值 的环境变量。但是,请注意分配到环境变量在 PowerShell / .NET没有区分 $null'',以及 任何一个值都会导致取消定义(删除)目标环境变量。

注意:如果环境变量是由上面的赋值($env:FOO = ...)按需创建的,它将存在于当前进程和它创建的任何子进程 仅限 谢谢PetSerAl


以下内容主要由Ansgar Wiechers提供,Mathias R. Jessen补充:

Windows[*] 上,如果您想定义环境变量永久,需要使用[System.Environment]类的静态SetEnvironmentVariable()方法:

# user environment
[Environment]::SetEnvironmentVariable('FOO', 'bar', 'User')

# system environment (requires admin privileges)
[Environment]::SetEnvironmentVariable('FOO', 'bar', 'Machine')

请注意,这些定义在未来会话(进程)中生效,因此为了当前进程定义变量也是如此,运行$env:FOO = 'bar' 另外,这实际上与[Environment]::SetEnvironmentVariable('FOO', 'bar', 'Process') 相同。

[Environment]::SetEnvironmentVariable()UserMachine 一起使用时,会向其他应用程序发送WM_SETTINGCHANGE 消息以通知它们更改(尽管很少有应用程序对此类通知做出反应)。 这不适用于定位Process(或分配给$env:FOO)时,因为无论如何其他应用程序(进程)都无法看到该变量。

See also.


[*] 在类似 Unix 的平台上,针对持久作用域 UserMachine 的尝试会被悄悄忽略,从 .NET (Core) 5 开始,这 鉴于缺乏跨 Unix 平台的统一机制,不支持定义持久性环境变量不太可能改变。

【讨论】:

【参考方案2】:

代码

function Set-LocalEnvironmentVariable 
    param (
        [Parameter()]
        [System.String]
        $Name,

        [Parameter()]
        [System.String]
        $Value,

        [Parameter()]
        [Switch]
        $Append
    )
    if($Append.IsPresent)
    
        if(Test-Path "env:$Name")
        
            $Value = (Get-Item "env:$Name").Value + $Value
        
    
    Set-Item env:$Name -Value "$value" | Out-Null


function Set-PersistentEnvironmentVariable 
    param (
        [Parameter()]
        [System.String]
        $Name,
    
        [Parameter()]
        [System.String]
        $Value,
    
        [Parameter()]
        [Switch]
        $Append        
    )
    
    Set-LocalEnvironmentVariable -Name $Name -Value $Value -Append:$Append
    if ($Append.IsPresent) 
        $value = (Get-Item "env:$Name").Value
    
    
    if ($IsWindows) 
        setx "$Name" "$Value" | Out-Null
        return
    
    $pattern = "\s*export[ \t]+$Name=[\w]*[ \t]*>[ \t]*\/dev\/null[ \t]*;[ \t]*#[ \t]*$Name\s*"
    
    if ($IsLinux) 
        $file = "~/.bash_profile"
        $content = (Get-Content "$file" -ErrorAction Ignore -Raw) + [System.String]::Empty
        $content = [System.Text.RegularExpressions.Regex]::Replace($content, $pattern, [String]::Empty);
        $content += [System.Environment]::NewLine + [System.Environment]::NewLine + "export $Name=$Value > /dev/null ;  # $Name"
        Set-Content "$file" -Value $content -Force
        return
    
    if ($IsMacOS) 
        $file = "~/.zprofile"
        $content = (Get-Content "$file" -ErrorAction Ignore -Raw) + [System.String]::Empty
        $content = [System.Text.RegularExpressions.Regex]::Replace($content, $pattern, [String]::Empty);
        $content += [System.Environment]::NewLine + [System.Environment]::NewLine + "export $Name=$Value > /dev/null ;  # $Name"
        Set-Content "$file" -Value $content -Force
        return
    
    throw "Invalid platform."


函数 Set-PersistentEnvironmentVariable 在实际过程和系统中设置变量/值。该函数调用Set-LocalEnvironmentVariable函数来设置进程范围变量,并在机器范围内执行设置变量的任务。

在 Windows 上您可以使用:

[Environment]::SetEnvironmentVariable 具有机器范围,用户或机器不能在 Linux 或 MacOS 上工作 setx 命令

在 Linux 上,我们可以将 export VARIABLE_NAME=Variable value 添加到文件 ~/.bash_profile。对于新的 bash 终端,该进程执行位于 ~/.bash_profile 中的这些指令。

在类似于 Linux 的 MacOS 上,但如果您有 zsh 终端,则文件为 .zprofile,如果默认终端为 bash,则该文件是 .bash_profile。在我的功能代码中,如果您愿意,我们需要添加对默认终端的检测。我假设默认终端是 zsh

函数 Set-LocalEnvironmentVariable 在实际过程中设置变量/值。使用云端硬盘 env:

示例

#Set "Jo" value to variable "NameX", this value is accesible in current process and subprocesses, this value is accessible in new opened terminal.
Set-PersistentEnvironmentVariable -Name "NameX" -Value "Jo"; Write-Host $env:NameX

#Append value "ma" to current value of variable "NameX", this value is accesible in current process and subprocesses, this value is accessible in new opened terminal.
Set-PersistentEnvironmentVariable -Name "NameX" -Value "ma" -Append; Write-Host $env:NameX

#Set ".JomaProfile" value to variable "ProfileX", this value is accesible in current process/subprocess.
Set-LocalEnvironmentVariable "ProfileX" ".JomaProfile"; Write-Host $env:ProfileX



输出

Windows 10

Ubuntu WSL


参考文献

查看About Environment VariablesShell initialization filesZSH: .zprofile, .zshrc, .zlogin - What goes where?

【讨论】:

以上是关于如果 PowerShell 中的环境变量不存在,如何设置它?的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell 中的环境变量,名称中带有点 (.)

(23)Powershell中的首选项变量

Powershell - 如何为 Start-Job 预先评估脚本块中的变量

显示正在运行的 PowerShell 脚本中的所有环境变量

Mac 环境变量配置

无法将环境变量传递给 azure 管道 yaml 中的 powershell 脚本(非内联)