Identifying Primary PowerShell Module Location

by Jan 28, 2022

PowerShell is just a scripting engine. All of its cmdlets come from external modules, and the environment variable $env:PSModulePath returns the folders that PowerShell automatically scans for modules:

 
PS> $env:PSModulePath -split ';'
C:\Users\username\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules 
 

Likewise, Get-Module finds all modules and cmdlets located in one of these folders:

Get-Module -ListAvailable

When you use PowerShell professionally, it becomes increasingly important to ensure that all required modules (and their cmdlets) are available. The first step therefore is to pick a good location to store new modules, and the next step is a good procedure to deploy and update such modules.

The best place to locally store modules is the folder representing the ”AllUsers” scope. On Windows systems, this folder is located in Program Files, and you need Administrator privileges to change it.

The best method to deploy and update modules in large enterprises is to use the existing software deployment infrastructure and deploy modules and their updates to the “AllUsers” folders identified earlier.

The path to this folder may vary based on the PowerShell version you use. Here is a script that calculates the path to the module location for all users:

# determine the primary module location for your PowerShell version
$path = if ('Management.Automation.Platform' -as [Type])
{
  # PowerShell CLR
  if ([Environment]::OSVersion.Platform -like 'Win*' -or $IsWindows) {
    # on Windows
    Join-Path -Path $env:ProgramFiles -ChildPath 'PowerShell'
  }
  else 
  {
    # on Non-Windows
    $name = [Management.Automation.Platform]::SelectProductNameForDirectory('SHARED_MODULES')
    Split-Path -Path $name -Parent
  }
}
else
{
  # Windows PowerShell
  Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell"
}

On Windows, PowerShell 7 and Windows PowerShell can share a folder, so above script can be further simplified if you do not want to deploy modules exclusively to PowerShell 7:

# determine the primary module location for your PowerShell version
$path = if ([Environment]::OSVersion.Platform -like 'Win*' -or $IsWindows)
{
  # Windows
  Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell"
}
else
{
  # Non-Windows
  $name = [Management.Automation.Platform]::SelectProductNameForDirectory('SHARED_MODULES')
  Split-Path -Path $name -Parent
}

$path


Twitter This Tip! ReTweet this Tip!