WPS = Windows PowerShell
PSC = PowerShell Core
When I started, I had three (3) paths as part of the System environment variable 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. But, I removed the first two to see if the PowerShells could find their own way or if they needed them?
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
. After that, WPS 5.1 and ISE start correctly.
Does WPS 5 -need- the System32 directory in the PSModulePath
before it starts? I would like to remove it. And, actually, 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, so I do not think any of the six (6) profile scripts (12 if 32-bit is added) is a good place. What do you suggest?
Update
=== start 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
As an aside, re:
PSC 6.2 [7.0] starts ok. There is no ISE.
The ISE is a self-contained executable that hosts PowerShell, not the other way around. It can only host Windows PowerShell, not PowerShell Core, so you cannot use it to develop PowerShell Core code.
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?"
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.
By contrast, the Windows PowerShell-only ISE will see no new features. (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.)
WPS 5.1 64-bit appears to start ok, but ISE reports an error finding
ISE
.
Omitting directory $env:SYSTEMROOT\system32\WindowsPowerShell\v1.0\Modules
from $env:PSModulePath
is ill-advised and results in the following symptoms:
Commands from the important system (shipped-with-Windows PowerShell) modules located there are still executable, because PowerShell apparently implicitly consults this location.
However, command discovery, tab completion, and explicit calls to Import-Module
by module name (as opposed to full path) then stop working:
ISE
module (among others) with ipmo ISE
(Import- Module
), which fails.New-ISESnippet -?
.When it comes to determining the effective $env:PSModulePath
value, the PS editions differ fundamentally:
Windows PowerShell (WPS) uses complicated rules to determine what directories to automatically add to $env:PSModulePath
; in short:
$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
).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 Core (WPC):
completely ignores any preexisting registry-based definitions of $env:PSModulePath
and always defines its own list of standard dirs. 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).
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.[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. via a preexisting $env:PSModulePath
environment-variable value, not replacing it.
Ignoring the registry-based definitions makes sense in that users may have used it to point to directories containing WSM-only modules. 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.
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
Without modifying the registry-based definition of $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.
Edition-specifically, you can choose:
$env:ProgramFiles\WindowsPowerShell\Modules
$env:ProgramFiles\PowerShell\Modules
With modifying the registry-based definition of $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.
Regrettably, as of this writing, that won't work for PSC, because it ignores registry-based definitions, as stated.
[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; e.g., 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.
Aside from that, this selective ignoring of environment-variable values depending on their method of definition is highly obscure.