Inside a script, I import a module, for example
Import-Module -Name Test -Scope Local
I execute the script at the command prompt
test.ps1
Then, after the script finishes, I run Get-Module
and the imported module shows up (though the functions, etc are not available).
Is it possible to prevent this without adding a Remove-Module
? (would add complexity to my scripts so I'd rather avoid it)
As Mathias points out in the comments, the behavior is documented - surprising as it may be (emphasis added):
Get-Module
shows all modules loaded in the current session. This includes modules loaded locally in a descendant scope. UseGet-Command -Module modulename
to see which members are loaded in the current scope.
If Get-Command -Module <your-module-name-or-path>
yields no output , the implication is that the module was imported locally in a descendent scope and that its members are not accessible in the calling scope.
In other words:
The "pollution" of the global scope is limited to Get-Module
's output - this is unexpected and confusing, but otherwise benign.
The only way to avoid it would indeed be to call Remove-Module
before exiting the script's scope.
Caveat:
If you target a module by name only with Import-Module
, as in your code (Test
), importing it will only succeed if it is located in one of the directories listed in the $env:PSModulePath
environment variable.
If it is, it is by default subject to module auto-loading, except if the defaults have been modified via the $PSModuleAutoLoadingPreference
preference variable.
This means that, by default, an attempt to call a command exported by a module discoverable via $env:PSModulePath
is automatically and session-globally loaded (imported), and this behavior also applies to calling Get-Command -Module
. The upshot is:
If you attempt to call a command from the given module, in the global scope, the module is then loaded globally.
If your script with the local import of auto-loading module Test
never ran in a given session, Get-Command -Module Test
will then load the module globally - it is only a prior non-global (local) import that prevents this behavior, which sounds more like a fallout from the implementation than a deliberate design choice: presumably, PowerShell in this case internally detects that the module has already been loaded, and then queries those module members visible to the calling scope - which are none in this case.