How does Powershell know where to find modules for import? How does Powershell know where to find modules for import? powershell powershell

How does Powershell know where to find modules for import?


While it is good practice to explicitly load the modules you want using Import-Module, since Powershell 3.0 if a module is available at one of the locations returned by $env:PSModulePath, it will automatically get loaded by default if one of its cmdlets are invoked. Below is a breakdown of the different paths:

User Modules

$modulePath = "${env:UserProfile}\Documents\WindowsPowerShell\Modules"Modules installed here are only available to the current user's Powershell session, and by default modules installed using Install-Module are saved here.

All User Modules

$modulePath = "${env:ProgramFiles}\WindowsPowerShell\Modules"Modules installed here are available to any users' Powershell session.

System Modules

$modulePath = "${env:SystemRoot}\system32\WindowsPowerShell\v1.0\Modules"Modules installed here are available system wide to any Powershell session, but should be kept clean for Windows to manage. Typically, you do not want to install your own modules here.

Adding Additional Module Paths

You can add additional paths to $env:PSModulePath similarly to how you would modify the $env:PATH variable for resolving executable paths. It is simply a semicolon ; delimited string of directories where modules reside, and if a module is available at any path in $env:PSModulePath, Powershell will know where to find it. And in fact, you may see that other installed tools may have added their own paths to $env:PSModulePath. A few of examples of programs/toolsets which do this are Microsoft SQL Studio, Microsoft System Center - Operations Manager, and the Chef Development Kit.

Importing a Module Not On the Path

As far as I know, you cannot load a Powershell module that is not a part of $env:PSModulePath. However, you can temporarily edit $env:PSModulePath to contain a directory with a module you want to load. For example, if you wanted to import a module named TestModule from some arbitrary path:

$env:PSModulePath += ';C:\Path\To\Temporary\ModuleDirectory'Import-Module TestModule

where TestModule exists as a sub-folder of C:\Path\To\Temporary\ModuleDirectory

You do not need to back out the module path change when you are ready to end your Powershell session as the change above is temporary. Consequently, you would need to modify $env:PSModulePath in every session, so if TestModule was something you wanted to have available at all times for use, you can either copy it to one of the other directories in $env:PSModulePath or permanently add C:\Path\To\Temporary\ModuleDirectory to the PSModulePath environment variable.

A Note About UNC Paths

You can also add UNC (network) paths to $env:PSModulePath. However, I believe any remote module scripts will still be subject to the Powershell ExecutionPolicy set on the system.

And a Bit More About Installing Modules

By default, Install-Module installs a module to the User Modules directory, but you can control this a bit with the -Scope parameter. For example, the following commands will change the location a module is installed into:

# Install to the current user location (default behavior if scope unspecified)Install-Module -Scope CurrentUser $moduleName# Install to the all users location (requires elevated permissions)Install-Module -Scope AllUsers $moduleName

Unfortunately, those are the only two locations PowerShell will assist you installing your modules to. The System modules are critical to the operation of PowerShell and should not be modified by end users, and additional paths added to $env:PSModulePath are likely managed by software outside of PowerShell, typically by MSIs or other installers.

Additionally, if you write software that ships with one or more PowerShell modules it's good practice to have your installer add a new directory to the system's %PSModulePath% and drop the module there, rather than installing to the standard AllUsers or CurrentUser path, as these are really meant for the end user to manage at their whim. Have your software update process update the module in this case. This has the benefit of preventing accidental modification or removal of the module to an incompatible version.