PowerShell 启动前的 PSModulePath 变量要求

PSModulePath variable requirements before PowerShell starts

WPS = Windows PowerShell
PSC = PowerShell 核心

开始时,我有三 (3) 个路径作为系统环境变量的一部分 PSModulePath

%ProgramFiles%\WindowsPowerShell\Modules
%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules
C:\Program Files (x86)\Microsoft SQL Server0\Tools\PowerShell\Modules\

我假设 SQL 服务器的安装创建了最后一个。但是,我删除了前两个以查看 PowerShell 是否可以找到自己的方式或者是否需要它们?

WPS 5.1 64-bit appears to start ok, but ISE reports an error finding `ISE`.
PSC 6.2 starts ok. There is no ISE.
PSC 7.0 starts ok. There is no ISE.

我不得不将 %SystemRoot%\system32\WindowsPowerShell\v1.0\Modules 目录放回到系统环境变量 PSModulePath 中。之后,WPS 5.1 和 ISE 正常启动。

WPS 5 在启动前是否需要 PSModulePath 中的 System32 目录?我想删除它。而且,实际上,我想将 SQL 服务器目录移动到更合适的位置。还有更好的地方吗?我经常 运行 powershell -NoProfile 来自 .bat 文件脚本,所以我认为六 (6) 个配置文件脚本(如果添加 32 位则为 12 个)中的任何一个都不是一个好地方。你有什么建议?

更新

===开始cmd.exe

C:>echo %PSModulePath%
C:\Program Files (x86)\Microsoft SQL Server0\Tools\PowerShell\Modules\;

=== 运行 powershell.exe 5.1.18362.145

C:>$Env:PSModulePath
C:\Users\lit\Documents\WindowsPowerShell\Modules;C:\Program Files (x86)\Microsoft SQL Server0\Tools\PowerShell\Modules\;C:\Program Files\WindowsPowerShell\Modules

=== 运行 是

ipmo : The specified module 'ISE' was not loaded because no valid module file was found in any module directory.
At line:1 char:1
+ ipmo ISE
+ ~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (ISE:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

顺便说一句,回复:

PSC 6.2 [7.0] starts ok. There is no ISE.

ISE 是 self-contained 可执行文件 hosts PowerShell,而不是相反。它只能承载WindowsPowerShell,不能承载PowerShellCore,所以你不能用它来开发PowerShellCore代码。

关于你的 follow-up 问题,"Should I expect there to ever be an ISE for PSC, or should I think VS Code is the thing to use?"

确实,Visual Studio Code with its PowerShell extension 是以后要使用的编辑器:它能够同时针对 Windows PowerShell 和 PowerShell Core,以及所有未来的开发努力将去那里。

相比之下,Windows PowerShell-only ISE 将看不到任何新功能。 (虽然 .NET Core 3.0 假设 为将 WPF-based ISE 移植到 .NET Core 铺平了道路,但我认为这不会发生。)


WPS 5.1 64-bit appears to start ok, but ISE reports an error finding ISE.

$env:PSModulePath 中省略目录 $env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules 是 ill-advised 并导致以下症状:

  • 位于那里的重要系统 (shipped-with-Windows PowerShell) 模块的命令仍然可执行,因为 PowerShell 显然 隐式参考这个位置。

  • 但是,命令发现、Tab 完成和显式 模块 nameImport-Module 的调用(与完整路径相反)然后停止工作:

    • 一个典型的例子是 ISE 的启动行为,它试图 显式地 加载 ISE 模块(以及其他模块) ipmo ISE (Import- Module),失败了。
    • 隐式加载模块仍然有效可以通过简单地直接调用其命令之一来验证,例如New-ISESnippet -?.

在确定有效 $env:PSModulePath 值时,PS 版本根本不同:

Windows PowerShell (WPS) 使用复杂的规则来确定要自动 添加到 $env:PSModulePath 的目录;简而言之:

  • all-users 模块目录,$env:ProgramFiles%\WindowsPowerShell\Modules 总是 自动添加,如果您 $env:PSModulePath值在注册表中预定义(默认情况下,它预定义的,并设置为$env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules)。
  • current-user 模块目录。仅在没有 user-level 注册表定义时添加。

  • 您可以使用 process-level$env:PSModulePath 设置临时 before 调用 powershell.exe.

PowerShell 核心 (WPC):

  • 完全忽略任何先前存在的registry-based定义$env:PSModulePath并始终定义其自己的标准目录列表。在启动时,包括 WPS 位置 加上 WPS' system-module 目录 、[=11= 的 PSC 对应项](因为越来越多的 WPS 系统模块也可用于 PSC)。

    • 此意外行为首次报告于 this GitHub issue、...
    • ... 导致 this RFC,在撰写本文时仍悬而未决,最终解决方案尚未确定。
  • 注入一个process-level$env:PSModulePath set ad hoc beforepowershell.exe 调用到其标准目录列表中,在 current-user 条目之后 - 假设值 与任何 registry-based 不同 ] 定义.[1]

    • 如果不是因为 registry-based 值和不同的临时值之间的模糊区别,PSC 的行为可以说是更明智的:它只允许 添加 到标准目录列表。通过预先存在的 $env:PSModulePath environment-variable 值,而不是 替换 它。

    • 忽略 registry-based 定义是有意义的,因为用户可能使用它指向包含 WSM-only 模块的目录。但是,如果为 PSC 选择了 不同的变量名称 ,则可以避免该问题 - 这确实是链接 RFC 中正在考虑的解决方案。


I would like to move the SQL Server directory to a more appropriate location. Is there a better place? I often run powershell -NoProfile from .bat file scripts

没有修改$env:PSModulePath的registry-based定义:

  • 唯一适用于 两个 版本的目录是 $env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules,但考虑到此目录用于 WPS, 不合适.

  • Edition-specifically,您可以选择:

    • WPS: $env:ProgramFiles\WindowsPowerShell\Modules
    • PSC:$env:ProgramFiles\PowerShell\Modules

修改$env:PSModulePath的registry-based定义:

  • 对于WPS,您可以在\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment处修改$env:PSModulePath的machine-level注册表定义(您也可以通过sysdm.cpl, Advanced > Environment Variables...): 将您选择的目录添加到那里的现有值。

  • 遗憾的是,在撰写本文时,这不适用于 PSC,因为它 忽略了 registry-based 定义ns,如前所述。


[1] 似乎对差异的测试执行得很草率,因为设置了一个临时值,其中 registry-based 值是 prefix匹配被认为是相同的;例如,如果在注册表中定义了值 c:\modules,则临时值 c:\modules.core 会使 PowerShell Core 认为临时值 不同并忽略它.
除此之外,这种根据定义方法选择性地忽略 environment-variable 值的做法非常晦涩。