about_PSModulePath

环境变量 $env:PSModulePath 包含搜索以查找模块和资源的文件夹位置的列表。 PowerShell 以递归方式在每个文件夹中搜索模块 (.psd1.psm1) 文件。

默认情况下,分配给 $env:PSModulePath 的有效位置为:

  • 系统范围的位置:这些文件夹包含 PowerShell 附带的模块。 这些模块存储在 $PSHOME\Modules 文件夹中。 这也是安装 Windows 管理模块的位置。

  • 用户安装的模块:这些是用户安装的模块。 Install-Module 具有 一个 Scope 参数,可用于指定是针对当前用户还是为所有用户安装模块。 有关详细信息,请参阅 Install-Module

    • 在 Windows 上,特定于用户的 CurrentUser 范围的位置是 $HOME\Documents\PowerShell\Modules 文件夹。 AllUsers 作用域的位置为 $env:ProgramFiles\PowerShell\Modules
    • 在非 Windows 系统上,特定于用户的 CurrentUser 范围的位置是 $HOME/.local/share/powershell/Modules 文件夹。 AllUsers 作用域的位置为 /usr/local/share/powershell/Modules

此外,在其他目录(如 Program Files 目录)中安装模块的安装程序可以将其位置追加到 的值 $env:PSModulePath

注意

在 Windows 上,特定于用户的位置是 PowerShell\Modules 位于用户配置文件中 “文档” 文件夹中的文件夹。 该位置的特定路径因 Windows 版本以及是否使用文件夹重定向而有所不同。 Microsoft OneDrive 还可以更改 Documents 文件夹的位置。 可以使用以下命令验证 Documents 文件夹的位置: [Environment]::GetFolderPath('MyDocuments')

PowerShell PSModulePath 构造

每次 PowerShell 启动时,都会构造 的值 $env:PSModulePath 。 该值因 PowerShell 版本及其启动方式而异。

Windows PowerShell启动

Windows PowerShell使用以下逻辑在启动时构造 PSModulePath

  • 如果 PSModulePath 不存在,请合并 CurrentUserAllUsers$PSHOME 模块路径
  • 如果 PSModulePath 存在:
    • 如果 PSModulePath 包含 $PSHOME 模块路径:
      • 在模块路径之前$PSHOME插入 AllUsers 模块路径
    • else:
      • 只需按定义使用PSModulePath,因为用户故意删除了位置$PSHOME

仅当用户范围$env:PSModulePath不存在时,CurrentUser 模块路径才具有前缀。 否则,将按定义使用用户范围 $env:PSModulePath

PowerShell 7 启动

在 Windows 中,对于大多数环境变量,如果存在用户范围的变量,则新进程仅使用该值,即使存在同名的计算机范围变量也是如此。

在 PowerShell 7 中, PSModulePath 的处理方式类似于在 Windows 上处理环境变量的方式 Path 。 在 Windows 上, Path 的处理方式与其他环境变量不同。 启动进程时,Windows 会将用户范围 Path 与计算机范围的 Path合并。

  • 检索用户范围 PSModulePath
  • 与进程继承的 PSModulePath 环境变量进行比较
    • 如果相同:
      • AllUsersPSModulePath 追加到环境变量语义的 Path 末尾
      • Windows System32 路径来自定义的 PSModulePath 计算机,因此无需显式添加
    • 如果不同,则视为用户显式修改它,不要追加 AllUsersPSModulePath
  • 按该顺序添加 PS7 用户、系统和 $PSHOME 路径的前缀
    • 如果 powershell.config.json 包含用户范围 PSModulePath,请使用 ,而不是用户的默认值
    • 如果 powershell.config.json 包含系统范围的 PSModulePath,请使用 它,而不是系统的默认值

Unix 系统不分离用户和系统环境变量。 PSModulePath 继承,如果尚未定义,则为特定于 PS7 的路径添加前缀。

从 PowerShell 7 开始Windows PowerShell

对于此讨论,Windows PowerShell意味着 powershell.exepowershell_ise.exe

$env:PSModulePath通过以下修改将 WinPSModulePath 的值复制到 中:

  • 删除 PS7 用户模块路径
  • 删除 PS7 系统模块路径
  • 删除 PS7 $PSHOME 模块路径

将删除 PS7 路径,这样 PS7 模块就不会加载到 Windows PowerShell中。 启动WinPSModulePathWindows PowerShell时使用 值。

从 Windows PowerShell 启动 PowerShell 7

PowerShell 7 启动会按原样继续,并添加Windows PowerShell添加的继承路径。 由于 PS7 特定的路径具有前缀,因此没有功能问题。

模块搜索行为

PowerShell 以递归方式在 PSModulePath 中的每个文件夹中搜索模块 (.psd1.psm1) 文件。 此搜索模式允许将同一模块的多个版本安装在不同的文件夹中。 例如:

    Directory: C:\Program Files\WindowsPowerShell\Modules\PowerShellGet

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/14/2020  5:56 PM                1.0.0.1
d----           9/13/2019  3:53 PM                2.1.2

默认情况下,当找到多个版本时,PowerShell 会加载模块的最高版本号。 若要加载特定版本,请将 与 FullyQualifiedName 参数一起使用Import-Module。 有关详细信息,请参阅 Import-Module

修改 PSModulePath

在大多数情况下,应在默认模块位置安装模块。 但是,可能需要更改环境变量的值 PSModulePath

例如,若要暂时将当前会话的 C:\Program Files\Fabrikam\Modules 目录 $env:PSModulePath 添加到 ,请键入:

$Env:PSModulePath = $Env:PSModulePath+";C:\Program Files\Fabrikam\Modules"

命令中的分号 (;) 将新路径与列表中的路径分隔开。 在非 Windows 平台上,冒号 (:) 分隔环境变量中的路径位置。

在非 Windows 中修改 PSModulePath

若要更改非 Windows 环境中每个会话的值 PSModulePath ,请将上一个命令添加到 PowerShell 配置文件。

在 Windows 中修改 PSModulePath

若要更改 Windows 环境中每个会话的值 PSModulePath ,请编辑用于存储值的 PSModulePath 注册表项。 这些 PSModulePath 值作为 未展开 的字符串存储在注册表中。 若要避免将值永久保存 PSModulePath扩展 字符串,请在子键上使用 GetValue 方法并直接编辑值。

以下示例将 C:\Program Files\Fabrikam\Modules 路径添加到环境变量的值, PSModulePath 而不展开未展开的字符串。

$key = (Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager').OpenSubKey('Environment', $true)
$path = $key.GetValue('PSModulePath','','DoNotExpandEnvironmentNames')
$path += ';C:\Program Files\Fabrikam\Modules' # or '%ProgramFiles%\Fabrikam\Modules'
$key.SetValue('PSModulePath',$path,[Microsoft.Win32.RegistryValueKind]::ExpandString)

若要将路径添加到用户设置,请将注册表提供程序从 HKLM:\ 更改为 HKCU:\

$key = (Get-Item 'HKCU:\SYSTEM\CurrentControlSet\Control\Session Manager').OpenSubKey('Environment', $true)
$path = $key.GetValue('PSModulePath','','DoNotExpandEnvironmentNames')
$path += ';C:\Program Files\Fabrikam\Modules' # or '%ProgramFiles%\Fabrikam\Modules'
$key.SetValue('PSModulePath',$path,[Microsoft.Win32.RegistryValueKind]::ExpandString)

另请参阅