如何检查是否安装了PowerShell模块?


97

要检查模块是否存在,我尝试了以下方法:

try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}

输出为:

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

我确实收到了一个错误,但是没有引发异常,因此Module exists尽管SomeModule不存在,但最后我们看到了。

有没有一种好的方法(最好不产生错误)来检测系统上是否安装了PowerShell模块?


Answers:


126

您可以使用以下ListAvailable选项Get-Module

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

1
我要去建议:Import-Module NonexistingModule -ErrorAction SilentlyContinue IF($ error){写主机'模块不存在'} ELSE {写主机'模块确实存在'}但是您的方法更好,更优雅:)
Erik Blomgren 2015年

这很好。谢谢。我会用,Write-Warning "Module does not exist..." ;Break但是您已经完成了所有艰苦的工作。
Craig.C

如果要使用Import-Module和自定义dll文件导入库,请不要使用该-ListAvailable选项来确定模块是否已安装,因为它不会列出。根据PowerShell 6文档,“即使在当前会话中加载了模块,ListAvailable也不会返回有关PSModulePath环境变量中找不到的模块的信息”。
Dave F

这不会确定是否已安装模块(即Import-Module),只会确定模块是否可立即用于安装而不指定未指定的特定位置$env:PSModulePath
Slogmeister Extraordinaire

34

ListAvailable选项对我不起作用。而是这样做:

if (-not (Get-Module -Name "<moduleNameHere>")) {
    # module is not loaded
}

或者,更简洁地说:

if (!(Get-Module "<moduleNameHere>")) {
    # module is not loaded
}

@oɔɯǝɹ我以为-ListAvailable根本不可用,但我仍在尝试Import-Module。使用Get-Module很好
Craig.C 2016年

3
您检查模块LOADED(本身是否有用-systemcentercentral.com/…),但其他答案则不会检查模块是否存在。
Michael Freidgeim '01

1
这比使用ListAvailable的执行速度快得多。
GaTechThomas

完全确定!根据版本不同,PowerShell中不起作用吗?
Kolob峡谷

2
@KolobCanyon!是的别名-not,但我一般不建议在ps1脚本中使用别名。@GaTechThomas它也具有不同的行为,如@MichaelFreidgeim所指定(它不会为已安装但未导入的模块返回真实值)。
AndreasHassing

28

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

  • 进口的
  • 在磁盘(或本地网络)上可用
  • 在线画廊中可用

如果您只想在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 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

1
这是一个很棒的“多合一”解决方案(我只更改了Load-Module以返回$ true / $ false而不是EXIT)
Andrzej Martyna,

这很漂亮。
肖恩

17

当前版本的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...
}

13

只是重新审视一下,因为这是我刚刚遇到的问题,并且答案中包含一些不正确的内容(尽管评论中已提及)。

第一件事。原始问题询问如何判断是否已安装PowerShell模块。我们需要谈论安装这个词!您无需安装PowerShell模块(无论如何都不能以传统方式安装软件)。

PowerShell模块可用(即,它们在PowerShell模块路径上),或者已导入(它们已导入到会话中,您可以调用其中包含的功能)。如果您想知道模块的存储位置,这是检查模块路径的方法:

$env:psmodulepath

我认为使用C:\ Program Files \ WindowsPowerShell \ Modules变得很普遍由于该模块可供所有用户使用,因此使用频率较高,但是如果您想将模块锁定到自己的会话中,则可以将其包含在个人资料中。C:\ Users \%username%\ Documents \ WindowsPowerShell \ Modules;

好了,回到两个州。

该模块是否可用(使用时表示在原始问题中已安装)?

Get-Module -Listavailable -Name <modulename>

这告诉您是否可以导入模块。

是否导入模块?(我将其用作原始问题中“存在”一词的答案)。

Get-module -Name <modulename>

如果未导入模块,则将返回空负载,如果没有导入,则返回一个一行的描述。与堆栈溢出一样,在您自己的模块上尝试上述命令。


1
您可以在PowerShell中安装模块。PowerShellGet的命令Get-InstalledModule返回的输出与Get-Module -ListAvailable
Igor的

9

当我在脚本中使用非默认模块时,将调用以下函数。除了模块名称,您还可以提供最低版本。

# 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
        } 
    }
}

用法示例:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'

请告诉我它是否有用(或无效)


4

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

#Requires语句将阻止脚本运行,除非满足PowerShell版本,模块,管理单元以及模块和管理单元版本先决条件。

因此,在脚本顶部,只需添加 #Requires -Module <ModuleName>

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

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


3

恕我直言,检查模块之间是否存在差异:

1)已安装,或2)导入:

要检查是否已安装:

选项1:Get-Module-ListAvailable参数一起使用:

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'}

要检查是否导入:

使用Get-Modulewith-Name参数(您可以忽略它,因为它是默认值):

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

3
try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}

应该指出的是,您的cmdletImport-Module没有终止错误,因此不会捕获异常,因此无论您的catch语句如何,都永远不会返回您编写的新语句。

https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6

从上面:

“终止错误会阻止语句运行。如果PowerShell无法以某种方式处理终止错误,那么PowerShell也会停止使用当前管道运行函数或脚本。在其他语言中,例如C#,终止错误称为异常。有关错误的更多信息,请参见about_Errors。”

它应写为:

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

哪个返回:

nope

并且,如果您确实想彻底了解,则应在运行其他功能/ cmdlet之前添加其他建议的cmdlet,Get-Module -ListAvailable -NameGet-Module -Name要格外小心。并且,如果它是从psgallery或其他地方安装的,则还可以运行Find-Modulecmdlet来查看是否有可用的新版本。


3

您可以使用 Get-InstalledModule

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

这里有很多好的答案,但是使用这种新的简单方法,这应该应该是新接受的答案。
not2qubit

1
  • 首先测试模块是否已加载
  • 然后导入

```

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
}

```


1

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

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


1

这是检查是否安装了AZ模块的代码:

$checkModule = "AZ"

$Installedmodules = Get-InstalledModule

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

    "$checkModule is installed "

}

else {

    "$checkModule is not installed"

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.