PowerShell环境变量:深入了解

使用 PowerShell 设置 Windows 环境变量,读取环境变量并创建新的环境变量一旦你掌握了诀窍就很容易。本文介绍的技巧适用于 Windows 10 环境变量以及 Windows 7 SP1/Windows Server 2008 之后的任何 Windows 客户端/服务器。

PowerShell 提供了许多与 Windows 环境变量交互的不同方式,包括从 $env: PSDrive、注册表和 [System.Environment] .NET 类。您将逐步了解每种方法,包括了解环境变量作用域。

假设

在本文中,我将使用 Windows 10 上的 Windows PowerShell 5.1。但如果您在 Windows 7 SP1 或更高版本上拥有任何版本的 Windows PowerShell v3 之后的版本,我即将展示的技术应该也能很好地工作。

什么是环境变量?

环境变量,顾名思义,存储了由 Windows 和应用程序使用的环境信息。环境变量可以被图形应用程序(如 Windows 资源管理器)和纯文本编辑器(如记事本)以及 cmd.exe 和 PowerShell 访问。

使用环境变量有助于在 PowerShell 脚本或模块中避免硬编码文件路径、用户名、计算机名等内容。

常见的环境变量

当您开始学习如何在 PowerShell 中使用环境变量时,您将遇到许多不同的变量。有些比其他变量更有用。以下是一些常见环境变量及其用途的参考。

Variable Usage
ClientName The name of the remote computer connected via a Remote Desktop session.
SessionName This helps to identify if the current Windows session is regarded by the operating system as running at the console. For console sessions SessionName will be ‘Console’. Enhanced Session connections to Hyper-V Virtual Machines do not report SessionName as ‘Console’, whereas Standard Sessions do.
ComputerName The name of the computer.
SystemRoot and Windir The path to the current Windows installation.
ProgramFiles and ProgramFiles(x86) The default locations for x64 and x86 programs.
ProgramW6432 The default location for programs, avoiding 32/64 bit redirection. This variable only applies for 32 bit processes running on a 64 bit platform. This means that you can use it to identify when a 32 bit instance of PowerShell is running on a 64 bit system.
UserDNSDomain The Fully Qualified Domain Name of the Active Directory domain that the current user logged on to. Only present for domain logons.
UserDomain The NETBIOS-style name of the domain that the current user logged on to. Can be a computer name if there’s no domain.
UserDomainRoamingProfile The location of the central copy of the roaming profile for the user, if any. Only present for domain logons.
UserName The name of the currently logged on user.
UserProfile The location of the profile of the current user on the local computer.

环境变量范围

有三个范围的环境变量。将范围视为构建起来形成完整图像的变量层。组合起来,这些“层”向 Windows 中的任何运行进程提供许多不同的环境变量。

环境变量范围“层次结构”

这些“层”中的每一个都可以组合或覆盖彼此。它们按照层次结构定义,如下所示:机器 –> 用户 –> 进程,每个范围的变量都会覆盖父范围中存在的变量。

例如,一个常见的环境变量是 TEMP。此变量存储了指向 Windows 本地临时文件夹的文件夹路径。此环境变量设置为:

  • C:\WINDOWS\TEMP in the machine scope
  • C:\Users\<username>\AppData\Local\Temp in the user scope
  • C:\Users\<username>\AppData\Local\Temp in the process scope.

如果在用户范围内没有设置TEMP环境变量,那么最终结果将是C:\WINDOWS\TEMP

环境变量范围类型

在 Windows 中有三种不同的环境变量范围。

机器

机器范围内的环境变量与运行的 Windows 实例相关联。任何用户帐户都可以读取这些变量,但设置、更改或删除它们需要使用提升的特权进行操作。

用户

环境变量在用户范围内与运行当前进程的用户相关联。用户变量会覆盖具有相同名称的机器-范围变量。

注意:Microsoft建议机器和用户范围的环境变量值不超过2048个字符。

进程

进程范围内的环境变量是机器用户范围的组合,以及Windows动态创建的一些变量。

以下是运行进程可用的环境变量列表。所有这些变量都是动态创建的。

  • ALLUSERSPROFILE
  • APPDATA
  • COMPUTERNAME
  • HOMEDRIVE
  • HOMEPATH
  • LOCALAPPDATA
  • LOGONSERVER
  • PROMPT
  • PUBLIC
  • SESSION
  • SystemDrive
  • SystemRoot
  • USERDNSDOMAIN
  • USERDOMAIN
  • USERDOMAIN_ROAMINGPROFILE
  • USERNAME
  • USERPROFILE

注册表中的环境变量

环境变量存储在两个注册表位置,一个用于用户范围,另一个用于机器范围。

不要使用注册表来管理环境变量

在注册表中更改变量时有一个注意事项。任何正在运行的进程都不会看到注册表中的变量更改。除非Windows通知它们发生了变化,否则进程只会看到启动进程时存在的注册表变量和值。

您可以使用.NET类直接修改注册表,而不是直接修改注册表。.NET [System.Environment]类可以修改机器和用户范围的环境变量,并为您处理注册表维护。

直接在注册表中修改环境变量,虽然可能,但没有意义。.NET类提供了一种更简单、受Microsoft支持的方法。您将在本文稍后了解如何使用[System.Environment] .NET类。

环境变量注册表位置和查询

I hope you’ve been convinced to not modify the registry directly but if you’d like to take a peek at what’s in there, you can find all user environment variables in the HKEY_CURRENT_USER\Environment key. Machine-scoped environment variables are stored at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.

这两个键中都包含类型为REG_SZREG_EXPAND_SZ的注册表值。REG_EXPAND_SZ值包含作为其值的一部分嵌入的环境变量。检索值时,这些环境变量将被展开。

要演示这一点,使用REG实用程序。这是Windows附带的一个小型命令行实用程序。

查询以下所示的TEMP环境变量。使用REG命令和QUERY参数运行以检索TEMP变量的值。

> REG QUERY HKCU\Environment /V TEMP

HKEY_CURRENT_USER\Environment     
    TEMP    REG_EXPAND_SZ    %USERPROFILE%\AppData\Local\Temp

有时您会注意到环境变量被百分号符号(%COMPUTERNAME%)包围,就像上面那样显示。这是通过cmd.exe和批处理文件显示环境变量的老式方式。请注意,PowerShell不识别此格式。

REG实用程序允许我们查看注册表值的原始值。值类型为REG_EXPAND_SZ,值包含%USERPROFILE%环境变量。

如果您更愿意使用PowerShell来检索注册表值,可以使用下面显示的Get-Item命令。

PS51> Get-ItemProperty -Path HKCU:\Environment -Name TEMP

TEMP         : C:\Users\<your username>\AppData\Local\Temp
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Environment
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER
PSChildName  : Environment
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry

通过GUI查看和设置Windows环境变量

要查看用户和系统环境变量的GUI视图,请从PowerShell、命令提示符或从Windows键+R运行SystemPropertiesAdvanced.exe 以显示系统属性高级选项卡。单击下面图像中突出显示的环境变量按钮。

The System Properties dialog, Advanced tab

如下所示的环境变量对话框允许您查看、创建和修改用户和机器范围的环境变量。请注意,该对话框将机器范围的变量称为系统变量

The Environment Variables dialog

现在您已经了解了环境变量,让我们来谈谈您来这里的目的,使用PowerShell管理它们

您可以通过几种不同的方式使用PowerShell来交互操作环境变量。

  • “Env:” PSDrive和Provider – 基于会话的。只为当前的PowerShell会话设置环境变量的值
  • “$env:”变量 – 基于会话的。只为当前的PowerShell会话设置环境变量的值
  • “[System.Environment]” .NET 类 – 允许您在多个会话和重启后保持用户和系统级别的环境变量

“Env:” PSDrive和Provider

读取环境变量的最佳方式之一是一个被称为PowerShell驱动器(PS驱动器)的PowerShell概念。PS驱动器允许您通过“Env:”驱动器将环境变量视为文件系统。

切换到“Env:”驱动器

像所有的PS驱动器一样,您可以通过像“Env:\TEMP”、“Env:\COMPUTERNAME”等路径来引用它。但为了节省一些按键次数,您可以像切换到任何文件系统驱动器一样切换到“Env:”驱动器,如下所示。

PS51> cd Env:
PS51 Env:\>

## 或

PS51> Set-Location Env:
PS Env:\>

使用“Env:”驱动器的标签自动完成功能

您可以使用与访问文件系统相同的命令,例如Get-ItemGet-ChildItem来访问环境变量。但是,您是在读取Env:驱动器而不是文件系统。

由于环境变量存储在PS驱动器中,您可以使用PowerShell的选项补全功能来循环访问可用的变量,如下所示。

Env: tab completion – finding environment variables starting with the letter C

现在,让我们来看几个如何使用Env: PS驱动器处理环境变量的示例。

使用Env:列出环境变量

PS51> Get-Item -Path Env:
PS51> Get-Item -Path Env:USERNAME

使用Env:和通配符列出环境变量

PS51> Get-Item -Path Env:user*

使用Env:查找环境变量的值

这些命令的结果是键/值[System.Collections.DictionaryEntry].NET对象。这些对象在Name属性中保存环境变量的名称,在Value属性中保存值。

您可以通过将Get-Item命令引用包装在括号中,并引用Value属性来访问环境变量的特定值,如下所示:

PS51> (Get-Item -Path Env:computername).Value
MYCOMPUTERHOSTNAME

在需要仅返回特定环境变量的情况下,使用标准的 PowerShell cmdlet,例如 Select-ObjectWhere-Object 来选择和过滤由 Env: 提供程序返回的对象。

在下面的示例中,仅返回环境变量 COMPUTERNAME

PS51> Get-ChildItem -Path Env: | Where-Object -Property Name -eq 'COMPUTERNAME'

作为另一种方法,使用 Get-Content cmdlet。此 cmdlet 返回包含环境变量值的 [String] 对象。该对象更容易处理,因为它仅返回值,而不是带有 NameValue 属性的对象。

PS51> Get-Content -Path Env:\COMPUTERNAME

演示:将环境值插入字符串

使用 Get-Content,您可以找到环境变量的值并将环境变量 COMPUTERNAME 例如,插入到文本字符串中。

PS51> 'Computer Name is: {0}' -f (Get-Content -Path Env:COMPUTERNAME)
Computer Name is: MYCOMPUTER

使用 Env: 设置环境变量(并创建)

使用 New-Item cmdlet 在 PowerShell 中创建新的环境变量。如下所示,为 Name 值提供环境变量的名称形式为 Env:\<EnvVarName>,并为 Value 参数提供环境变量的值。

PS51> New-Item -Path Env:\MYCOMPUTER -Value MY-WIN10-PC
Name                           Value
----                           -----
MYCOMPUTER                     MY-WIN10-PC

使用Set-Item cmdlet设置环境变量,如果尚不存在,则创建一个新的。您可以通过使用Set-Item cmdlet来创建或修改环境变量。

PS51> Set-Item -Path Env:testvariable -Value "Alpha"

使用Env:复制环境变量

有时会出现需要复制环境变量值的情况。您可以使用Copy-Item cmdlet来实现。

如下所示,COMPUTERNAME变量的值被复制到MYCOMPUTER,覆盖了其现有值。

PS51> Get-Item -Path Env:\MYCOMPUTER

Name                           Value
----                           -----
MYCOMPUTER                     MY-WIN10-PC

PS51> Copy-Item -Path Env:\COMPUTERNAME -Destination Env:\MYCOMPUTER
PS51> Get-Item -Path Env:\MYCOMPUTER

Name                           Value
----                           -----
MYCOMPUTER                     WIN10-1903

使用Env:移除环境变量

会出现不再需要某个环境变量的情况。您可以使用以下三种方法之一来移除环境变量:

  • 使用Set-Item cmdlet将环境变量设置为空值
PS51> Set-Item -Path Env:\MYCOMPUTER -Value ''
PS51> Remove-Item -Path Env:\MYCOMPUTER
  • 使用Clear-Item cmdlet。
PS51> Clear-Item -Path Env:\MYCOMPUTER

使用Env:重命名环境变量

在需要更改环境变量名称的情况下,您可以选择重命名,而不是删除并使用Env:提供程序重新创建。

使用Rename-Item cmdlet来更改环境变量的名称,同时保留其值。下面你可以看到MYCOMPUTER变量被重命名为OLDCOMPUTER,同时保留其值。

PS51> Rename-Item -Path Env:\MYCOMPUTER -NewName OLDCOMPUTER
PS51> Get-Item -Path OLDCOMPUTER
Name                           Value
----                           -----
OLDCOMPUTER                    WIN10-1903

$Env: 变量

掌握了Env: 驱动器将环境变量视为文件后,本节将向你展示如何将其视为变量。管理会话内环境变量的另一种方法是使用PowerShell 表达式解析器。此功能允许你使用$Env: 作用域访问环境变量。

使用$Env:获取环境变量

使用$Env 作用域,你可以直接引用环境变量,而无需使用Get-Item 命令,如下所示。

PS51> $env:computername

这种方法使得将环境变量插入字符串变得很容易,如下所示:

PS51> "The Computer Name is {0}" -f $env:computername
The Computer Name is WIN10-1809
PS51> "The Computer Name is $env:computername"
The Computer Name is WIN10-1809

使用$Env:设置或创建环境变量

使用此方法设置环境变量非常简单。这也将创建一个新的环境变量,如果还不存在的话,如下所示。

PS51> $env:testvariable = "Alpha"

使用+=语法来添加到现有值,而不是覆盖它。

PS51> $env:testvariable = "Alpha"
PS51> $env:testvariable += ",Beta"

PS51> $env:testvariable
Alpha,Beta

使用$Env:删除环境变量

使用此方法删除环境变量,只需将其值设置为空字符串。

PS51> $env:testvariable = ''

使用 [System.Environment] .NET 类

.NET 类 [System.Environment] 还提供了获取和设置环境变量的方法。这是直接访问各种环境范围并设置在 PowerShell 会话中持久存在的环境变量的唯一方法。

在以下所有示例中,如果未提供范围,则假定为进程范围。

使用 [System.Environment] 时,您将使用几种不同的 .NET 静态类 方法。您不需要了解静态方法是什么。您只需要了解使用您即将学习的任何技术,您需要首先引用类([System.Environment]),然后是两个冒号(::),然后是方法。

使用 [System.Environment] 列出环境变量

如果您想要查看特定范围内的所有环境变量,则可以使用 GetEnvironmentVariables 方法。此方法将按指定为方法参数的范围返回所有环境变量(括号内)。

Listing environment variables with GetEnvironmentVariable in each scope
PS51> [System.Environment]::GetEnvironmentVariables('User') PS51> [System.Environment]::GetEnvironmentVariables('Machine') PS51> [System.Environment]::GetEnvironmentVariables('Process') # 与进程相同 PS51> [System.Environment]::GetEnvironmentVariables()

使用 [System.Environment] 获取单个环境变量

如果您需要查找特定环境变量,可以通过两种不同的方式进行。

  • GetEnvironmentVariables().<var name> – 不推荐
  • GetEnvironmentVariable('<var name>','<scope>')

GetEnvironmentVariables()

使用GetEnvironmentVariables()方法时,您可以使用点表示法来引用值。将[System.Environment]类和静态方法引用括在括号内,然后跟一个点,再跟环境变量的名称,如下所示:

PS51> ([System.Environment]::GetEnvironmentVariables()).APPDATA

请注意,使用这种方式引用环境变量时,必须确保大小写匹配!在上面的示例中,尝试使用appdata来引用APPDATA变量。请使用GetEnvironmentVariable()代替。

GetEnvironmentVariable()

与使用GetEnvironmentVariables()方法不同,使用GetEnvironmentVariable()来查找单个环境变量。它可以解决大小写问题,还允许您指定作用域。

要使用此方法,请指定环境变量名称和您要查找该变量的作用域,用逗号分隔。

PS51> [System.Environment]::GetEnvironmentVariable('ComputerName','User')
# 空

PS51> [System.Environment]::GetEnvironmentVariable('ComputerName','Machine')
# 空

PS51> [System.Environment]::GetEnvironmentVariable('ComputerName','Process')  WIN10-1903

# 与进程相同
PS51> [System.Environment]::GetEnvironmentVariable('ComputerName')
WIN10-1903

使用[System.Environment]设置环境变量

使用SetEnvironmentVariable()方法为给定的作用域设置环境变量的值,如果尚不存在,则创建一个新的。

在设置过程范围内的变量时,您会发现过程范围是易变的,而对用户和机器范围的更改是永久的。

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable','Alpha','User')

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable','Alpha','Process')

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable','Alpha','Machine')

 # 与Process相同
PS51> [System.Environment]::SetEnvironmentVariable('TestVariable','Alpha')

注意:使用变量名或值长度为32767个字符或更多的SetEnvironmentVariable方法调用会引发异常。

使用[System.Environment]删除环境变量

通过将其值设置为空字符串,使用SetEnvironmentVariable()方法为给定范围删除环境变量。

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable', '', 'User')

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable', '', 'Process')

PS51> [System.Environment]::SetEnvironmentVariable('TestVariable', '', 'Machine')

# 与process相同
PS51> [System.Environment]::SetEnvironmentVariable('TestVariable', '')

有用的PowerShell环境变量

像许多其他Windows应用程序一样,PowerShell有一些自己的环境变量。需要了解的两个有用的环境变量是PSExecutionPolicyPreferencePSModulePath

PSExecutionPolicyPreference

PSExecutionPolicyPreference环境变量存储当前的PowerShell执行策略。如果通过以下方式设置了特定于会话的PowerShell执行策略,则会创建它:

  • 使用Scope参数的Set-ExecutionPolicy cmdlet运行
  • 运行powershell.exe可执行文件以启动新会话,使用ExecutionPolicy命令行参数为会话设置策略。

PSModulePath

PSModulePath 环境变量包含 PowerShell 在未指定完整路径时搜索模块的路径。其格式与标准的 PATH 环境变量类似,各个目录路径由分号分隔。

PS51> $env:PSModulePath
C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules

小提示:使用 $env:PSModulePath.split(‘;’) 可以将每个文件夹拆分成字符串数组,以便逐个处理每个路径。

摘要

环境变量是获取有关运行中系统信息或在会话和重启之间存储信息的有用方法。无论是仅读取默认的 Windows 操作系统环境变量并创建自己的变量,您现在都可以使用 PowerShell 以多种方式管理它们!

更多阅读

Source:
https://adamtheautomator.com/powershell-environment-variables/