[英]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: output 是:
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.我确实得到了一个错误,但没有抛出异常,所以我们看到
Module exists
,尽管SomeModule
不存在。
Is there a good way (preferably without generating an error) to detect if a PowerShell module is installed on the system?有没有一种好方法(最好不会产生错误)来检测系统上是否安装了 PowerShell 模块?
You can use the ListAvailable
option of Get-Module
:您可以使用
Get-Module
的ListAvailable
选项:
if (Get-Module -ListAvailable -Name SomeModule) { Write-Host "Module exists" } else { Write-Host "Module does not exist" }
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:如果您只想在 PowerShell session 中使用该死的东西,这里有一个 function 可以做到这一点,如果它不能完成它就退出:
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
The ListAvailable option doesn't work for me. ListAvailable 选项对我不起作用。 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 }
The current version of Powershell has a Get-InstalledModule
function that suits this purpose well (or at least it did in my case).当前版本的 Powershell 有一个
Get-InstalledModule
function 非常适合这个目的(或者至少在我的情况下是这样)。
Get-InstalledModule
Description
描述
The
Get-InstalledModule
cmdlet gets PowerShell modules that are installed on a computer.Get-InstalledModule
cmdlet 获取安装在计算机上的 PowerShell 模块。
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.唯一的问题是,如果被请求的模块不存在,它会抛出异常,所以我们需要适当地设置
ErrorAction
来抑制这种情况。
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
您可以使用
Get-InstalledModule
If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) { Write-Host "Module does not exist" } Else { Write-Host "Module exists" }
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.
原始问题询问如何判断是否安装了 PowerShell 模块。 We need to talk about the word installed.
我们需要谈谈安装这个词。 You don't install PowerShell modules (not in the traditional way you install software anyway)
您不安装 PowerShell 模块(不是以传统方式安装软件)
PowerShell modules are either available (ie they are on the PowerShell module path), or they are imported (they are imported into your session and you can call the functions contained). PowerShell 模块要么可用(即它们在 PowerShell 模块路径上),要么它们被导入(它们被导入到您的 session 中,您可以调用包含的函数)。 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;我认为使用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.
更常见的是因为它对所有用户都可用,但如果您想将模块锁定到您自己的 session,请将它们包含在您的配置文件中。 C:\Users%username%\Documents\WindowsPowerShell\Modules;
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.
与 Stack Overflow 上一样,在您自己的模块上尝试上述命令。
When I use non-default modules in my scripts I call the function below.当我在脚本中使用非默认模块时,我在下面调用 function。 Besides 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 -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 } } }
usage example:用法示例:
Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'
Please let me known if it's useful (or not)请让我知道它是否有用(或没有)
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 isn't being caught so no matter what your catch statement will never return the new statement you have written.应该指出的是,您的 cmdlet
Import-Module
没有终止错误,因此不会捕获异常,因此无论您的 catch 语句是什么,都不会返回您编写的新语句。
( https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6 ( https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6
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."
"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 . 有关错误的更多信息,请参阅 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.如果您真的想要彻底,您应该在运行其他功能/cmdlet 之前添加其他建议的 cmdlet
Get-Module -ListAvailable -Name
和Get-Module -Name
以格外小心。 And if it's installed from ps gallery or elsewhere you could also run a Find-Module
cmdlet to see if there is a new version available.如果它是从 ps 库或其他地方安装的,您还可以运行
Find-Module
cmdlet 以查看是否有可用的新版本。
You can use the #Requires
statement (supports modules from PowerShell 3.0).您可以使用
#Requires
语句(支持来自 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.
#Requires 语句会阻止脚本运行,除非满足 PowerShell 版本、模块、管理单元以及模块和管理单元版本的先决条件。
So At the top of the script, simply add #Requires -Module <ModuleName>
所以在脚本的顶部,只需添加
#Requires -Module <ModuleName>
If the required modules are not in the current session, PowerShell imports them.
如果所需模块不在当前 session 中,则 PowerShell 导入它们。
If the modules cannot be imported, PowerShell throws a terminating error.
如果无法导入模块,PowerShell 会抛出终止错误。
IMHO, there is difference between checking if a module is:恕我直言,检查模块是否为:
1) installed, or 2) imported: 1) 已安装,或 2) 导入:
To check if installed:检查是否安装:
Option 1: Using Get-Module
with -ListAvailable
parameter:选项 1:使用带有
-ListAvailable
参数Get-Module
:
If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'} Else{'Module is NOT installed'}
Option 2: Using $error
object:选项 2:使用
$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):将
Get-Module
与-Name
参数一起使用(您可以忽略它,因为它是默认值):
if ((Get-Module -Name "<ModuleName>")) { Write-Host "Module is already imported (ie its cmdlets are available to be used.)" } else { Write-Warning "Module is NOT imported (must be installed before importing)." }
``` ```
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 }
``` ```
Coming from Linux background.来自 Linux 背景。 I would prefer using something similar to grep, therefore I use Select-String.
我更喜欢使用类似于 grep 的东西,因此我使用 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
Get-Module -ListAvailable -All | Select-String Module_Name
(can be a part of the module name) Get-Module -ListAvailable -All | Select-String Module_Name
(可以是模块名称的一部分)
Here is the code to check if AZ module is installed or not:这是检查是否安装了 AZ 模块的代码:
$checkModule = "AZ" $Installedmodules = Get-InstalledModule if ($Installedmodules.name -contains $checkModule) { "$checkModule is installed " } else { "$checkModule is not installed" }
The absolute simplest one-liner without if-else block using Az
module as an example:以
Az
模块为例,没有 if-else 块的绝对最简单的单行代码:
Get-InstalledModule Az
This is what you want if you're working in the shell console and just want to check if a PowerShell module is installed or not.如果您在 shell 控制台中工作并且只想检查是否安装了 PowerShell 模块,这就是您想要的。
Because this came up in so many answers, I am posting this as a separate answer instead of several comments.因为这出现在很多答案中,所以我将其作为单独的答案而不是几条评论发布。 Please consider this as a public service announcement.
请将此视为公共服务公告。
The answers based on using Get-InstalledModule
are extremely dangerous if you really want to know if a module is available on a PowerShell
installation.如果您真的想知道某个模块在
PowerShell
安装中是否可用,则基于使用Get-InstalledModule
的答案非常危险。 Get-InstalledModule
will report the presence of a module only if it has been installed from PowerShellGet.仅当从 PowerShellGet 安装模块时,
Get-InstalledModule
才会报告模块的存在。
Evidence from PowerShell:来自 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
There are no parameters for Get-InstalledModule
that you can use to tell it to "show the other modules that you just aren't displaying right now." Get-InstalledModule
没有参数可用于告诉它“显示您现在不显示的其他模块”。 It can't display any others.它不能显示任何其他内容。 As you can see above, it only shows 2 modules installed when I have 9 imported into my session
正如您在上面看到的,当我将 9 个模块导入 session 时,它只显示安装了 2 个模块
Since this is an answer, I will add endorsements here:由于这是一个答案,我将在此处添加背书:
-ListAvailable
parameter does not actually list all available modules.-ListAvailable
参数实际上并未列出所有可用模块。 But practically, most of us probably don't care too much because if ListAvailable
doesn't return a module, then we can't use it unless we already know how to load it using a non-standard/manual method, in which case we are unlikely to be searching for it to begin with.ListAvailable
不返回模块,那么除非我们已经知道如何使用非标准/手动方法加载它,否则我们将无法使用它,在这种情况下我们不太可能一开始就搜索它。 So like I said, my best answer is to read other people's answers, but please do not walk away from this page thinking that Get-InstalledModule
is a reliable way to determine if a module is installed (locally importable by name) on your PowerShell installation).所以就像我说的,我最好的答案是阅读其他人的答案,但请不要离开这个页面,认为
Get-InstalledModule
是一种可靠的方法来确定您的 PowerShell 安装中是否安装了模块(按名称本地导入) )。 That is just not what it's for.那不是它的用途。 It will supply you the names of modules installed by PowerShellGet , but it will not supply you with the names of any other locally installed modules.
它将为您提供由PowerShellGet安装的模块的名称,但不会为您提供任何其他本地安装的模块的名称。
Test-Path "C:\Program Files\WindowsPowerShell\Modules\ModuleName"
If you know the module name and common install paths, you could use:如果您知道模块名称和常用安装路径,则可以使用:
$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
}
Don't get me wrong, Get-module -listAvailable |不要误会我的意思,Get-module -listAvailable | where {$_.name -eq "ModuleName"} works very well, it just takes too long for me if you have a lot of modules installed.
{$_.name -eq "ModuleName"} 工作得很好,如果你安装了很多模块,这对我来说太长了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.