To check if a module exists I have tried the following:
try {
Import-Module SomeModule
Write-Host "Module exists"
}
catch {
Write-Host "Module does not exist"
}
The output is:
Import-Module : The specified module 'SomeModule' was not loaded because no valid module file was found in any module directory.
At D:\keytalk\Software\Client\TestProjects\Export\test.ps1:2 char:5
+ Import-Module SomeModule
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (SomeModule:String) [Import-Module], FileNotFoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
Module exists
I do get an error, but no exception is thrown, so we see Module exists
in the end, although SomeModule
does not exist.
Is there a good way (preferably without generating an error) to detect if a PowerShell module is installed on the system?
This question is related to
powershell
The current version of Powershell has a Get-InstalledModule
function that suits this purpose well (or at least it did in my case).
Get-InstalledModule
Description
The
Get-InstalledModule
cmdlet gets PowerShell modules that are installed on a computer.
The only issue with it is that it throws an exception if the module that is being requested doesn't exist, so we need to set ErrorAction
appropriately to suppress that case.
if ((Get-InstalledModule `
-Name "AzureRm.Profile" `
-MinimumVersion 5.0 ` # Optionally specify minimum version to have
-ErrorAction SilentlyContinue) -eq $null) {
# Install it...
}
You can use the Get-InstalledModule
If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
Write-Host "Module does not exist"
}
Else {
Write-Host "Module exists"
}
try {
Import-Module SomeModule
Write-Host "Module exists"
}
catch {
Write-Host "Module does not exist"
}
It should be pointed out that your cmdlet Import-Module
has no terminating error, therefore the exception isnt being caught so no matter what your catch statement will never return the new statement you have written.
From The Above:
"A terminating error stops a statement from running. If PowerShell does not handle a terminating error in some way, PowerShell also stops running the function or script using the current pipeline. In other languages, such as C#, terminating errors are referred to as exceptions. For more information about errors, see about_Errors."
It should be written as:
Try {
Import-Module SomeModule -Force -Erroraction stop
Write-Host "yep"
}
Catch {
Write-Host "nope"
}
Which returns:
nope
And if you really wanted to be thorough you should add in the other suggested cmdlets Get-Module -ListAvailable -Name
and Get-Module -Name
to be extra cautious, before running other functions/cmdlets. And if its installed from psgallery or elsewhere you could also run a Find-Module
cmdlet to see if there is a new version available.
The ListAvailable option doesn't work for me. Instead this does:
if (-not (Get-Module -Name "<moduleNameHere>")) {
# module is not loaded
}
Or, to be more succinct:
if (!(Get-Module "<moduleNameHere>")) {
# module is not loaded
}
IMHO, there is difference between checking if a module is:
1) installed, or 2) imported:
To check if installed:
Option 1: Using Get-Module
with -ListAvailable
parameter:
If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'}
Else{'Module is NOT installed'}
Option 2: Using $error
object:
$error.clear()
Import-Module "<ModuleName>" -ErrorAction SilentlyContinue
If($error){Write-Host 'Module is NOT installed'}
Else{Write-Host 'Module is installed'}
To check if imported:
Using Get-Module
with -Name
parameter (which you can omit as it is default anyway):
if ((Get-Module -Name "<ModuleName>")) {
Write-Host "Module is already imported (i.e. its cmdlets are available to be used.)"
}
else {
Write-Warning "Module is NOT imported (must be installed before importing)."
}
When I use a non-default modules in my scripts I call the function below. Beside the module name you can provide a minimum version.
# See https://www.powershellgallery.com/ for module and version info
Function Install-ModuleIfNotInstalled(
[string] [Parameter(Mandatory = $true)] $moduleName,
[string] $minimalVersion
) {
$module = Get-Module -Name $moduleName -ListAvailable |`
Where-Object { $null -eq $minimalVersion -or $minimalVersion -ge $_.Version } |`
Select-Object -Last 1
if ($null -ne $module) {
Write-Verbose ('Module {0} (v{1}) is available.' -f $moduleName, $module.Version)
}
else {
Import-Module -Name 'PowershellGet'
$installedModule = Get-InstalledModule -Name $moduleName -ErrorAction SilentlyContinue
if ($null -ne $installedModule) {
Write-Verbose ('Module [{0}] (v {1}) is installed.' -f $moduleName, $installedModule.Version)
}
if ($null -eq $installedModule -or ($null -ne $minimalVersion -and $installedModule.Version -lt $minimalVersion)) {
Write-Verbose ('Module {0} min.vers {1}: not installed; check if nuget v2.8.5.201 or later is installed.' -f $moduleName, $minimalVersion)
#First check if package provider NuGet is installed. Incase an older version is installed the required version is installed explicitly
if ((Get-PackageProvider -Name NuGet -Force).Version -lt '2.8.5.201') {
Write-Warning ('Module {0} min.vers {1}: Install nuget!' -f $moduleName, $minimalVersion)
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Scope CurrentUser -Force
}
$optionalArgs = New-Object -TypeName Hashtable
if ($null -ne $minimalVersion) {
$optionalArgs['RequiredVersion'] = $minimalVersion
}
Write-Warning ('Install module {0} (version [{1}]) within scope of the current user.' -f $moduleName, $minimalVersion)
Install-Module -Name $moduleName @optionalArgs -Scope CurrentUser -Force -Verbose
}
}
}
usage example:
Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'
Please let me known if it's usefull (or not)
Coming from Linux background. I would prefer using something similar to grep, therefore I use Select-String. So even if someone is not sure of the complete module name. They can provide the initials and determine whether the module exists or not.
Get-Module -ListAvailable -All | Select-String Module_Name
(can be a part of the module name)
You can use the #Requires
statement (supports modules from PowerShell 3.0).
The #Requires statement prevents a script from running unless the PowerShell version, modules, snap-ins, and module and snap-in version prerequisites are met.
So At the top of the script, simply add #Requires -Module <ModuleName>
If the required modules are not in the current session, PowerShell imports them.
If the modules cannot be imported, PowerShell throws a terminating error.
A module could be in the following states:
If you just want to have the darn thing available in a PowerShell session for use, here is a function that will do that or exit out if it cannot get it done:
function Load-Module ($m) {
# If module is imported say that and do nothing
if (Get-Module | Where-Object {$_.Name -eq $m}) {
write-host "Module $m is already imported."
}
else {
# If module is not imported, but available on disk then import
if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $m}) {
Import-Module $m -Verbose
}
else {
# If module is not imported, not available on disk, but is in online gallery then install and import
if (Find-Module -Name $m | Where-Object {$_.Name -eq $m}) {
Install-Module -Name $m -Force -Verbose -Scope CurrentUser
Import-Module $m -Verbose
}
else {
# If module is not imported, not available and not in online gallery then abort
write-host "Module $m not imported, not available and not in online gallery, exiting."
EXIT 1
}
}
}
}
Load-Module "ModuleName" # Use "PoshRSJob" to test it out
Just revisiting this as it's something I just faced and there is some incorrect stuff in the answers (though it's mentioned in the comments).
First thing though. The original questions asks how to tell if a PowerShell module is installed. We need to talk about the word installed! You don't install PowerShell modules (not in the traditional way you install software anyway).
PowerShell modules are either available (i.e. they are on the PowerShell module path), or they are imported (they are imported into your session and you can call the functions contained). This is how to check your module path, in case you want to know where to store a module:
$env:psmodulepath
I'd argue that it's becoming common to use C:\Program Files\WindowsPowerShell\Modules; more often due to it being available to all users, but if you want to lock down your modules to your own session, include them in your profile. C:\Users\%username%\Documents\WindowsPowerShell\Modules;
Alright, back to the two states.
Is the module available (using available to mean installed in the original question)?
Get-Module -Listavailable -Name <modulename>
This tells you if a module is available for import.
Is the module imported? (I'm using this as the answer for the word 'exists' in the original question).
Get-module -Name <modulename>
This will either return an empty load of nothing if the module is not imported, or a one line description of the module if it is. As ever on Stack Overflow, try the commands above on your own modules.
```
if (Get-Module -ListAvailable -Name <<MODULE_NAME>>) {
Write-Verbose -Message "<<MODULE_NAME>> Module does not exist." -Verbose
}
if (!(Get-Module -Name <<MODULE_NAME>>)) {
Get-Module -ListAvailable <<MODULE_NAME>> | Import-Module | Out-Null
}
```
Here is the code to check if AZ module is installed or not:
$checkModule = "AZ"
$Installedmodules = Get-InstalledModule
if ($Installedmodules.name -contains $checkModule)
{
"$checkModule is installed "
}
else {
"$checkModule is not installed"
}
Source: Stackoverflow.com