PowerShell启动前PSModulePath变量的要求

3

WPS代表Windows PowerShell
PSC代表PowerShell Core

当我开始时,我的系统环境变量PSModulePath中有三个路径。

最初的回答:

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

我认为安装SQL Server创建了最后一个。但是,我删除了前两个,以查看PowerShells是否能够找到自己的方法或者它们是否需要它们?" 最初的回答
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之前,是否需要将System32目录添加到PSModulePath中?我想要删除它。实际上,我想将SQL Server目录移动到更合适的位置。有更好的位置吗?我经常从.bat文件脚本运行powershell -NoProfile,因此我不认为任何六(6)个配置文件脚本(如果添加32位,则为12个)是一个好地方。你有什么建议吗?

更新

===开始cmd.exe

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

=== run powershell.exe 5.1.18362.145

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

=== run ise

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

1
system32位置包含许多重要的模块(包括关键的PowerShell模块),而PsModulePath是PowerShell用来找到它们的方式。我可以理解SQL模块在非标准位置上,但为什么你想要移除其他位置呢? - undefined
1个回答

2
作为旁注,关于以下内容:

PSC 6.2 [7.0] 可以正常启动。没有 ISE。

ISE 是一个自包含的可执行文件,用于托管 PowerShell,而不是反过来。它只能托管 Windows PowerShell,而不能用于开发 PowerShell Core 代码。
关于您的后续问题,“我是否应该期望有一个 PSC 的 ISE,还是应该使用 VS Code?”确实,Visual Studio Code 与其PowerShell 扩展是未来要使用的编辑器:它能够针对 Windows PowerShell 和 PowerShell Core,所有未来的开发工作都将在那里进行。
相比之下,仅适用于 Windows PowerShell 的 ISE 将看不到新功能。(虽然 .NET Core 3.0 理论上为将基于 WPF 的 ISE 移植到 .NET Core 铺平了道路,但我认为这不会发生。)
关于以下内容:

WPS 5.1 64 位似乎可以正常启动,但 ISE 报告找不到 ISE 错误。

$env:PSModulePath 中省略目录 $env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules 是不明智的,并导致以下症状:
  • 位于此处的重要系统(随 Windows PowerShell 一起提供的)模块的命令仍然可执行,因为 PowerShell 显然会隐式地查询此位置。

  • 但是,命令发现、制表符补全和通过模块名称(而不是完整路径)显式调用 Import-Module 然后停止工作:

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

在确定有效的 $env:PSModulePath 值时,PowerShell 版本有根本性的区别: Windows PowerShell(WPS)使用复杂的规则来确定要自动添加到 $env:PSModulePath 的目录;简而言之:
  • 如果您的$env:PSModulePath值在注册表中预定义(默认情况下,它被预定义并设置为$env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules),则始终会自动添加all-users模块目录$env:ProgramFiles%\WindowsPowerShell\Modules
  • 只有在没有user-level注册表定义时,才会添加current-user模块目录。

  • 您可以使用临时设置的process-level$env:PSModulePath在调用powershell.exe之前覆盖所有注册表定义。

PowerShell Core (WPC):

  • 完全忽略任何现有的基于注册表的$env:PSModulePath定义,并始终在启动时定义其自己的标准目录列表,包括 PSC 对应于 WPS 位置的目录以及 WPS 的系统模块目录$env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules(因为越来越多的 WPS 系统模块也可从 PSC 中使用)。

  • 在当前用户条目之后 - 假设该值与任何基于注册表的定义不同[1],将process-level$env:PSModulePath设置临时注入到其标准目录列表中。

    • 如果不考虑基于注册表的值和不同的临时值之间的微妙区别,则 PSC 的行为可以说更合理:它仅允许通过预先存在的$env:PSModulePath环境变量值添加到标准目录列表中,而不是替换它。

    • 忽略基于注册表的定义是有道理的,因为用户可能已将其用于指向仅包含 WSM 模块的目录。但是,如果为 PSC 选择了一个不同的变量名,则可以避免这个问题-这确实是链接的 RFC 中正在考虑的解决方案。


我想将SQL Server目录移动到更合适的位置。有更好的地方吗?我经常从.bat文件脚本运行

不修改基于注册表的$env:PSModulePath定义:

  • 唯一可用于两个版本的目录是$env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules,但考虑到该目录是WPS随附的模块,这是不合适的。

  • 特定于版本,您可以选择:

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

修改基于注册表的$env:PSModulePath定义:

  • 对于WPS,您可以在\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment上修改机器级别的注册表定义$env:PSModulePath(您也可以通过sysdm.cpl高级 > 环境变量...进行修改):在现有值中添加您选择的目录。

  • 遗憾的是,截至本文撰写时,对于PSC,这不起作用,因为它忽略基于注册表的定义。


[1] 看起来差异测试实现得很草率,因为将一个临时值设置为注册表值的前缀匹配被认为是相同的;例如,如果在注册表中定义了值c:\modules,则临时值c:\modules.core使PowerShell Core认为临时值不同并忽略它。
除此之外,根据其定义方法选择性地忽略环境变量值是非常晦涩的。


我认为忽略注册表设置是好的。在PSC运行的其他平台上没有"注册表"。 - undefined
非常愉快,@lit;是的,Install-Module 只针对标准目录:使用 -Scope AllUsers 可以安装到标准的所有用户目录,使用 -Scope CurrentUser 可以安装到标准的当前用户目录(在 PSC 中是默认设置)。 - undefined
关于忽略注册表:是的,其他平台没有注册表,但它们有环境变量,并且在Windows中使用注册表是定义环境变量的官方方法。请注意,PSC确实尊重进程级别的$env:PSModulePath值,但仅当它们与基于注册表的定义不同时才生效,这是一个非常模糊的区别(而且实现得很粗糙-请参阅我添加的脚注)。 - undefined
@lit: 除了这个问题之外,PSC在表现上是合理的,它会将预先存在的PSModulePath环境变量中的目录添加到目录列表中,而不是覆盖标准目录。 - undefined
如果该值来自注册表,PSC将忽略它。尝试从注册表中删除它,并在调用PSC之前在您的cmd会话中设置它。 - undefined
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接