简体   繁体   English

PowerShell 启动前的 PSModulePath 变量要求

[英]PSModulePath variable requirements before PowerShell starts

WPS = Windows PowerShell WPS = Windows PowerShell
PSC = PowerShell Core PSC = PowerShell 核心

When I started, I had three (3) paths as part of the System environment variable PSModulePath .当我开始时,我有三 (3) 条路径作为系统环境变量PSModulePath

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

I assume that the install of SQL Server created the last one.我假设 SQL Server 的安装创建了最后一个。 But, I removed the first two to see if the PowerShells could find their own way or if they needed them?但是,我删除了前两个,看看 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.

I had to put back the %SystemRoot%\\system32\\WindowsPowerShell\\v1.0\\Modules directory into the System environment variable PSModulePath .我不得不将%SystemRoot%\\system32\\WindowsPowerShell\\v1.0\\Modules目录PSModulePath系统环境变量PSModulePath After that, WPS 5.1 and ISE start correctly.之后,WPS 5.1 和 ISE 正确启动。

Does WPS 5 -need- the System32 directory in the PSModulePath before it starts? WPS 5 在启动之前是否需要PSModulePath的 System32 目录? I would like to remove it.我想删除它。 And, actually, I would like to move the SQL Server directory to a more appropriate location.而且,实际上,我想将 SQL Server 目录移动到更合适的位置。 Is there a better place?有没有更好的地方? I often run powershell -NoProfile from .bat file scripts, so I do not think any of the six (6) profile scripts (12 if 32-bit is added) is a good place.我经常从 .bat 文件脚本运行powershell -NoProfile ,因此我认为六 (6) 个配置文件脚本(如果添加 32 位则为 12 个)中的任何一个都不适合。 What do you suggest?你有什么建议?

Update更新

=== start cmd.exe === 启动cmd.exe

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

=== run powershell.exe 5.1.18362.145 === 运行 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 === 运行 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

As an aside, re:顺便说一句,重新:

PSC 6.2 [7.0] starts ok. PSC 6.2 [7.0] 启动正常。 There is no ISE.没有ISE。

The ISE is a self-contained executable that hosts PowerShell, not the other way around. ISE 是一个独立的可执行文件,它托管PowerShell,而不是相反。 It can only host Windows PowerShell , not PowerShell Core , so you cannot use it to develop PowerShell Core code.它只能托管Windows PowerShell ,而不是 PowerShell Core ,因此您不能使用它来开发 PowerShell Core代码。

Re your follow-up question, "Should I expect there to ever be an ISE for PSC, or should I think VS Code is the thing to use?"关于你的后续问题,“我应该期待 PSC 有一个 ISE,还是我应该认为 VS Code 是可以使用的?”

Indeed, Visual Studio Code with its PowerShell extension is the editor to use going forward : It is capable of targeting both Windows PowerShell and PowerShell Core, and all future development effort will go there.事实上,带有PowerShell 扩展的Visual Studio Code是未来使用的编辑器:它能够同时针对 Windows PowerShell 和 PowerShell Core,并且所有未来的开发工作都将进行。

By contrast, the Windows PowerShell-only ISE will see no new features .相比之下,仅适用于 Windows PowerShell 的 ISE 将看不到任何新功能 (While .NET Core 3.0 hypothetically paves the way for porting the WPF-based ISE to .NET Core, I don't think that will happen.) (虽然 .NET Core 3.0假设为将基于 WPF 的 ISE 移植到 .NET Core 铺平了道路,但我认为这不会发生。)


WPS 5.1 64-bit appears to start ok, but ISE reports an error finding ISE . WPS 5.1 64 位似乎可以正常启动,但 ISE 报告发现ISE错误。

Omitting directory $env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules from $env:PSModulePath is ill-advised and results in the following symptoms:$env:PSModulePath省略目录$env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules是不明智的,会导致以下症状:

  • Commands from the important system (shipped-with-Windows PowerShell) modules located there are still executable , because PowerShell apparently implicitly consults this location.来自位于那里的重要系统(随 Windows PowerShell 一起提供)模块的命令仍然是 executable ,因为 PowerShell 显然隐式地咨询了这个位置。

  • However, command discovery, tab completion, and explicit calls to Import-Module by module name (as opposed to full path) then stop working:但是,命令发现、选项卡完成和按模块名称(而不是完整路径)显式调用Import-Module然后停止工作:

    • Case in point is the startup behavior of the ISE, which tries to explicitly load the ISE module (among others) with ipmo ISE ( Import- Module ), which fails.一个ipmo ISE的启动行为,它尝试使用ipmo ISEipmo ISE Import- Module显式加载ISE模块(以及其他Import- Module ),但失败了。
    • That implicitly loading the module still works can be verified by simply directly invoking one of its commands, eg, New-ISESnippet -?可以通过简单地直接调用其命令之一来验证隐式加载模块仍然有效,例如New-ISESnippet -? . .

When it comes to determining the effective $env:PSModulePath value, the PS editions differ fundamentally:在确定有效的$env:PSModulePath值时,PS 版本根本不同:

Windows PowerShell (WPS) uses complicated rules to determine what directories to automatically add to $env:PSModulePath ; Windows PowerShell (WPS) 使用复杂的规则来确定要自动添加到$env:PSModulePath in short:简而言之:

  • The all-users module dir., $env:ProgramFiles%\\WindowsPowerShell\\Modules is always automatically added, if your $env:PSModulePath value is predefined in the registry (by default, it is predefined, and set to $env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules ).所有的用户模块目录。 $env:ProgramFiles%\\WindowsPowerShell\\Modules总是自动添加,如果你的$env:PSModulePath值在注册表中预定义(默认情况下,它预定义的,并设置为$env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules )。
  • The current-user module dir.当前用户模块目录。 is only added if there's no user-level registry definition.仅在没有用户级注册表定义时才添加。

  • You can override all registry definitions with a process-level value of $env:PSModulePath set ad hoc before calling powershell.exe .调用powershell.exe之前,您可以使用进程级$env:PSModulePath临时设置来覆盖所有注册表定义。

PowerShell Core (WPC): PowerShell 核心 (WPC):

  • completely ignores any preexisting registry-based definitions of $env:PSModulePath and always defines its own list of standard dirs.完全忽略$env:PSModulePath任何预先存在的基于注册表的定义,并始终定义自己的标准目录列表。 on startup, comprising the PSC counterparts to the WPS locations plus WPS' system-module directory , $env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules (because an increasing number of WPS system modules are also usable from PSC).在启动时,包括 WPS 位置的 PSC 对应物以及 WPS 的系统模块目录$env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules (因为越来越多的 WPS 系统模块也可从 PSC 使用)。

    • This unexpected behavior was first reported in this GitHub issue , ...这种意外行为首先在此 GitHub 问题中报告,...
    • ... which led to this RFC , which is still pending as of this writing, with the ultimate resolution not yet decided. ...这导致了这个 RFC ,在撰写本文时仍在等待中,最终解决方案尚未确定。
  • injects a process-level value of $env:PSModulePath set ad hoc before calling powershell.exe into its list of standard directories, after the current-user entry - assuming that value differs from any registry-based definition.powershell.exe调用到其标准目录列表之前,在当前用户条目之后注入一个进程级$env:PSModulePath set ad hoc - 假设该值不同于任何基于注册表的定义。 [1] [1]

    • If it weren't for the obscure distinction between a registry-based value and a - differing - ad hoc value, PSC's behavior is arguably more sensible: it only allows adding to the list of standard dirs.如果不是基于注册表的值和一个不同的临时值之间的模糊区别,PSC 的行为可以说是更明智的:它只允许添加到标准目录列表。 via a preexisting $env:PSModulePath environment-variable value, not replacing it.通过预先存在的$env:PSModulePath环境变量值,而不是替换它。

    • Ignoring the registry-based definitions makes sense in that users may have used it to point to directories containing WSM-only modules.忽略基于注册表的定义是有意义的,因为用户可能已经使用它来指向包含仅 WSM 模块的目录。 If a different variable name had been chosen for PSC, however, that problem could have been avoided - and that's indeed a solution being considered in the linked RFC.但是,如果为 PSC 选择了不同的变量名称,则可以避免该问题 - 这确实是链接的 RFC 中正在考虑的解决方案。


I would like to move the SQL Server directory to a more appropriate location.我想将 SQL Server 目录移动到更合适的位置。 Is there a better place?有没有更好的地方? I often run powershell -NoProfile from .bat file scripts我经常从 .bat 文件脚本运行powershell -NoProfile

Without modifying the registry-based definition of $env:PSModulePath :修改$env:PSModulePath的基于注册表的定义:

  • The only directory that would work for both editions would be $env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules , but given that this directory is for module that ship with WPS, that's not appropriate.唯一适用于两个版本的目录是$env:SYSTEMROOT\\system32\\WindowsPowerShell\\v1.0\\Modules ,但鉴于此目录用于 WPS 附带的模块,这是不合适的。

  • Edition-specifically , you can choose:特定版本,您可以选择:

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

With modifying the registry-based definition of $env:PSModulePath :通过修改$env:PSModulePath的基于注册表的定义:

  • For WPS, you can modify the machine-level registry definition of $env:PSModulePath at \\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment (which you can also modify via sysdm.cpl , Advanced > Environment Variables... ): add your directory of choice to the existing value there.对于 WPS,您可以在\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment修改$env:PSModulePath的机器级注册表定义(您也可以通过sysdm.cplAdvanced > Environment Variables...修改) :您选择的目录添加到那里的现有值中。

  • Regrettably, as of this writing, that won't work for PSC, because it ignores registry-based definitions, as stated.遗憾的是,在撰写本文时,这对 PSC 不起作用,因为如上所述,它忽略了基于注册表的定义。


[1] It seems that the test for difference is sloppily implemented, in that setting an ad hoc value for which a registry-based value is a prefix match is considered identical; [1] 似乎差异测试的实施很草率,因为设置了一个基于注册表的值是前缀匹配的临时值被认为是相同的; eg, if value c:\\modules is defined in the registry, an ad hoc value of c:\\modules.core makes PowerShell Core think that the ad hoc value does not differ and ignores it.例如,如果值c:\\modules在注册表中定义,则c:\\modules.core临时值会使 PowerShell Core 认为临时值没有不同并忽略它。
Aside from that, this selective ignoring of environment-variable values depending on their method of definition is highly obscure.除此之外,这种根据环境变量的定义方法有选择地忽略环境变量值是非常模糊的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM