How do I check if a PowerShell module is installed?

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?

190822 次浏览

You can use the ListAvailable option of Get-Module:

if (Get-Module -ListAvailable -Name SomeModule) {
Write-Host "Module exists"
}
else {
Write-Host "Module does not exist"
}

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
}

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 ask 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.

恕我直言,检查一个模块是否是:

1)已安装,或 2)进口:

检查是否安装:

备选方案1: 使用带有 -ListAvailable参数的 Get-Module:

If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'}
Else{'Module is NOT installed'}

备选案文2: 使用 $error对象:

$error.clear()
Import-Module "<ModuleName>" -ErrorAction SilentlyContinue
If($error){Write-Host 'Module is NOT installed'}
Else{Write-Host 'Module is installed'}

检查是否输入:

使用带有 -Name参数的 Get-Module(因为它是 违约,所以可以省略它) :

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)."
}

一个模块可以处于以下状态:

  • 进口的
  • 磁盘(或本地网络)上可用
  • 在线图库中可以找到

如果你只是想在 PowerShell 会话中使用该死的东西,这里有一个函数可以做到这一点,如果它不能完成它就退出:

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 the module is not imported, not available and not in the online gallery then abort
write-host "Module $m not imported, not available and not in an online gallery, exiting."
EXIT 1
}
}
}
}


Load-Module "ModuleName" # Use "PoshRSJob" to test it out
  • 首先测试模块是否已加载
  • 那就进口

```

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
}

```

当前版本的 Powershell 有一个非常适合这一目的的 Get-InstalledModule功能(至少在我的例子中是这样)。

Get-InstalledModule

描述

Get-InstalledModulecmdlet 获取计算机上安装的 PowerShell 模块。

唯一的问题是,如果被请求的模块不存在,它会抛出异常,所以我们需要适当地设置 ErrorAction来抑制这种情况。

if ((Get-InstalledModule `
-Name "AzureRm.Profile" `
-MinimumVersion 5.0 ` # Optionally specify minimum version to have
-ErrorAction SilentlyContinue) -eq $null) {


# Install it...
}
try {
Import-Module SomeModule
Write-Host "Module exists"
}
catch {
Write-Host "Module does not exist"
}

应该指出的是,您的 cmdlet Import-Module没有终止错误,因此异常没有被捕获,所以无论您的 catch 语句是什么,都不会返回您编写的新语句。

(https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6

来自上面的:

”终止错误将停止语句的运行。如果 PowerShell 没有以某种方式处理终止错误,则 PowerShell 也会停止使用当前管道运行函数或脚本。在其他语言中,例如 C # ,终止错误被称为异常。有关错误的详细信息,请参阅 about _ Ererror。”

应该这样写:

Try {
Import-Module SomeModule -Force -Erroraction stop
Write-Host "yep"
}
Catch {
Write-Host "nope"
}

结果是:

nope

如果您真的希望全面了解,那么在运行其他函数/cmdlet 之前,应该添加其他建议的 cmdlet Get-Module -ListAvailable -NameGet-Module -Name,以便格外小心。如果它是从 ps 画廊或其他地方安装的,你也可以运行一个 Find-Modulecmdlet,看看是否有一个新的版本可用。

来自 Linux 背景。我更喜欢使用类似于 grep 的东西,因此我使用 Select-String。因此,即使有人不确定完整的模块名称。它们可以提供首字母缩写,并确定模块是否存在。

Get-Module -ListAvailable -All | Select-String Module_Name(可以是模块名称的一部分)

当我在脚本中使用非默认模块时,我调用下面的函数。除了模块名之外,还可以提供最小版本。

# 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 -lt $_.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
}
}
}

用法例子:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'

请让我知道它是否有用

下面是检查 AZ 模块是否安装的代码:

$checkModule = "AZ"


$Installedmodules = Get-InstalledModule


if ($Installedmodules.name -contains $checkModule)
{


"$checkModule is installed "


}


else {


"$checkModule is not installed"


}

可以使用 #Requires语句(支持 PowerShell 3.0中的模块)。

语句阻止脚本运行,除非 PowerShell 版本、模块、管理单元以及模块和管理单元版本 符合先决条件。

因此,在脚本的顶部,简单地添加 #Requires -Module <ModuleName>

如果所需的模块不在当前会话中,PowerShell 将导入它们。

如果无法导入模块,PowerShell 将引发 终止错误终止错误。

你可以使用 Get-InstalledModule

If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
Write-Host "Module does not exist"
}
Else {
Write-Host "Module exists"
}

使用 Az模块作为例子的没有 if-else 块的绝对最简单的一行程序:

Get-InstalledModule Az

如果您在 shell 控制台中工作,只是想检查是否安装了 PowerShell 模块,那么就需要这样做。

因为这个问题有很多答案,所以我把它作为一个独立的答案而不是一些评论。请把这当做公益广告。

如果您真的想知道 PowerShell安装中是否有模块可用,那么基于使用 Get-InstalledModule得到的答案是非常危险的。Get-InstalledModule将报告模块 除非它是从 PowerShellGet 安装的。的存在

来自 PowerShell 的证据:

PS C:\Users\chris> Get-InstalledModule | Select-Object -Property Name, Version


Name         Version
----         -------
Choco        1.0.0
NTFSSecurity 4.2.6


PS C:\Users\chris> Get-Module | Select-Object -Property Name, Version


Name                            Version
----                            -------
chocolateyProfile               0.0
CimCmdlets                      7.0.0.0
Microsoft.PowerShell.Management 7.0.0.0
Microsoft.PowerShell.Security   7.0.0.0
Microsoft.PowerShell.Utility    7.0.0.0
Microsoft.WSMan.Management      7.0.0.0
PackageManagement               1.4.7
PowerShellGet                   2.2.5
PSReadLine                      2.1.0

Get-InstalledModule没有参数可以用来告诉它“显示您现在没有显示的其他模块”它不能显示任何其他的。正如你可以看到上面,它只显示2模块安装时,我有9导入到我的会话!

既然这是一个答案,我将在这里加上支持:

  • @ Kieman Schindler 的回答(https://stackoverflow.com/a/28740512/1236579)很好。正如其他人所指出的,-ListAvailable参数实际上并没有列出所有可用的模块。但实际上,我们大多数人可能不会太在意,因为如果 ListAvailable不返回一个模块,那么我们就不能使用它,除非我们已经知道如何使用非标准/手动方法加载它,在这种情况下,我们不太可能一开始就搜索它。
  • 如果你需要更多的东西,我想@TJ Galama 和@Rod 已经为你提供了很好的剧本。

因此,正如我所说,我的最佳答案是阅读其他人的答案,但请做 没有离开这个页面,认为 Get-InstalledModule是一个可靠的方法,以确定是否安装了模块(本地可导入的名称)在您的 PowerShell 安装)。那不是它的用途。它提供由 PowerShellGet安装的模块的名称,但是 没有将提供任何其他本地安装的模块的名称。

Test-Path "C:\Program Files\WindowsPowerShell\Modules\ModuleName"

如果您知道模块名称和常见的安装路径,您可以使用:

$a = New-Object -TypeName 'System.Collections.ArrayList'


$paths = "$env:userprofile\*\ModuleName","C:\Program
Files\WindowsPowerShell\Modules\ModuleName"


foreach ($path in $paths)
{
$a.add($(Test-path $path))
}


If ($a -contains $true)
{
Write-Host "ModuleName is installed" -ForegroundColor Green
}
else
{
Write-Host "ModuleName is not installed" -foregroundcolor Red
}

不要误解我的意思,Get-module-listable | where { $_。Name-eq“ ModuleName”}工作得非常好,只是如果您安装了很多模块,那么对我来说花费的时间太长了。