Comment vérifier si un module PowerShell est installé?

92

Pour vérifier si un module existe, j'ai essayé ce qui suit:

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

La sortie est:

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

Je reçois une erreur, mais aucune exception n'est levée, donc nous voyons Module existsà la fin, bien qu'il SomeModulen'existe pas.

Existe-t-il un bon moyen (de préférence sans générer d'erreur) de détecter si un module PowerShell est installé sur le système?

Klemens Schindler
la source

Réponses:

119

Vous pouvez utiliser l' ListAvailableoption de Get-Module:

if (Get-Module -ListAvailable -Name SomeModule) {
    Write-Host "Module exists"
} 
else {
    Write-Host "Module does not exist"
}
Klemens Schindler
la source
1
J'allais suggérer: Import-Module NonexistingModule -ErrorAction SilentlyContinue IF ($ error) {Le module Write-Host 'n'existe pas'} ELSE {Le module Write-Host 'existe'} Mais votre chemin est meilleur, plus élégant :)
Erik Blomgren le
Cela fonctionne très bien. Merci. Je vais utiliser Write-Warning "Module does not exist..." ;BreakMais vous avez fait tout le travail dur.
Craig.C
Si vous importez des bibliothèques à l'aide d' Import-Moduleun fichier dll personnalisé, n'utilisez pas l' -ListAvailableoption pour déterminer si le module est installé car il ne sera pas répertorié. Selon la documentation PowerShell 6 , «ListAvailable ne renvoie pas d'informations sur les modules qui ne sont pas trouvés dans la variable d'environnement PSModulePath, même si ces modules sont chargés dans la session en cours».
Dave F le
Cela ne détermine pas si un module a été installé (c'est-à-dire Import-Module) il détermine uniquement si le module est immédiatement disponible pour être installé sans spécifier un emplacement spécifique qui n'est pas déjà dans$env:PSModulePath
Slogmeister Extraordinaire
35

L'option ListAvailable ne fonctionne pas pour moi. Au lieu de cela, cela fait:

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

Ou, pour être plus succinct:

if (!(Get-Module "<moduleNameHere>")) {
    # module is not loaded
}
Karezza
la source
@ oɔɯǝɹ Je pensais que -ListAvailable n'était tout simplement pas disponible mais j'essayais toujours Import-Module. Avec Get-Module, tout va bien
Craig.C
2
Vous vérifiez si le module LOADED (qui est utile en lui-même - systemcentercentral.com / ... ), mais pas l'autre réponse vérifie si le module existe.
Michael Freidgeim
1
Cela s'exécute beaucoup plus rapidement que d'utiliser ListAvailable.
GaTechThomas
Assez sûr que !cela ne fonctionne pas dans PowerShell selon la version?
Kolob Canyon
2
@KolobCanyon !est un alias pour -not, mais je ne recommanderais pas l'utilisation d'alias dans les scripts ps1 en général. @GaTechThomas il a également un comportement différent, comme spécifié par @MichaelFreidgeim (il ne renvoie pas de valeur de vérité pour les modules installés, mais pas importés).
AndreasHassing le
27

Un module peut être dans les états suivants:

  • importé
  • disponible sur disque (ou réseau local)
  • disponible dans la galerie en ligne

Si vous voulez simplement que le truc sacrément soit disponible dans une session PowerShell pour une utilisation, voici une fonction qui le fera ou se fermera si elle ne peut pas le faire:

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
Barre
la source
1
c'est une excellente solution "tout-en-un" (j'ai seulement changé Load-Module pour retourner $ true / $ false au lieu de EXIT)
Andrzej Martyna
17

La version actuelle de Powershell a une Get-InstalledModulefonction qui convient bien à cet objectif (ou du moins c'était le cas dans mon cas).

Get-InstalledModule

La description

L' Get-InstalledModuleapplet de commande obtient les modules PowerShell installés sur un ordinateur.

Le seul problème avec cela est qu'il lève une exception si le module demandé n'existe pas, nous devons donc définir de ErrorActionmanière appropriée pour supprimer ce cas.

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

    # Install it...
}
NightOwl888
la source
13

Je revisite simplement cela car c'est quelque chose que je viens de rencontrer et il y a des choses incorrectes dans les réponses (bien que cela soit mentionné dans les commentaires).

Première chose cependant. Les questions d'origine demandent comment savoir si un module PowerShell est installé. Il faut parler du mot installé! Vous n'installez pas de modules PowerShell (pas de toute façon de la manière traditionnelle que vous installez le logiciel).

Les modules PowerShell sont soit disponibles (c'est-à-dire qu'ils se trouvent sur le chemin du module PowerShell), soit ils sont importés (ils sont importés dans votre session et vous pouvez appeler les fonctions contenues). Voici comment vérifier le chemin de votre module, au cas où vous voudriez savoir où stocker un module:

$env:psmodulepath

Je dirais qu'il est de plus en plus courant d'utiliser C: \ Program Files \ WindowsPowerShell \ Modules; plus souvent parce qu'il est disponible pour tous les utilisateurs, mais si vous souhaitez verrouiller vos modules à votre propre session, incluez-les dans votre profil.C: \ Users \% username% \ Documents \ WindowsPowerShell \ Modules;

Très bien, revenons aux deux états.

Le module est-il disponible (en utilisant disponible pour signifier installé dans la question d'origine)?

Get-Module -Listavailable -Name <modulename>

Cela vous indique si un module est disponible pour l'importation.

Le module est-il importé? (J'utilise ceci comme réponse au mot «existe» dans la question d'origine).

Get-module -Name <modulename>

Cela renverra soit une charge vide de rien si le module n'est pas importé, soit une description d'une ligne du module si c'est le cas. Comme toujours sur Stack Overflow, essayez les commandes ci-dessus sur vos propres modules.

bytejunkie
la source
1
Vous pouvez installer le module dans PowerShell. PowerShellGet a une commande Get-InstalledModulequi ne renvoie pas la même sortie queGet-Module -ListAvailable
Igor
9

Lorsque j'utilise des modules non par défaut dans mes scripts, j'appelle la fonction ci-dessous. À côté du nom du module, vous pouvez fournir une version minimale.

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

exemple d'utilisation:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'

S'il vous plaît laissez-moi savoir si c'est utile (ou pas)

TJ Galama
la source
4

Vous pouvez utiliser l' #Requiresinstruction (prend en charge les modules de PowerShell 3.0).

L'instruction #Requires empêche un script de s'exécuter à moins que la version PowerShell, les modules, les composants logiciels enfichables et les conditions préalables de la version du module et du composant logiciel enfichable ne soient remplies.

Donc, en haut du script, ajoutez simplement #Requires -Module <ModuleName>

Si les modules requis ne sont pas dans la session actuelle, PowerShell les importe.

Si les modules ne peuvent pas être importés, PowerShell renvoie une erreur de fin.

Sheldonzy
la source
3

À mon humble avis, il y a une différence entre vérifier si un module est:

1) installé, ou 2) importé:

Pour vérifier s'il est installé:

Option 1: Utilisation Get-Moduleavec -ListAvailableparamètre:

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

Option 2: Utilisation de l' $errorobjet:

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

Pour vérifier si importé:

Utilisation Get-Moduleavec -Nameparamètre (que vous pouvez omettre car il est par défaut de toute façon):

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)."
}
Eddie Kumar
la source
3
try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}

Il convient de souligner que votre applet de commande Import-Modulen'a pas d'erreur de fin, par conséquent l'exception n'est pas interceptée, donc quelle que soit votre instruction catch ne retournera jamais la nouvelle instruction que vous avez écrite.

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

D'en haut:

"Une erreur de fin arrête l'exécution d'une instruction. Si PowerShell ne gère pas une erreur de fin d'une manière ou d'une autre, PowerShell arrête également d'exécuter la fonction ou le script à l'aide du pipeline actuel. Dans d'autres langages, tels que C #, les erreurs de fin sont appelées exceptions . Pour plus d'informations sur les erreurs, consultez about_Errors. "

Il doit être écrit comme suit:

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

Qui retourne:

nope

Et si vous voulez vraiment être minutieux, vous devez ajouter les autres applets de commande suggérées Get-Module -ListAvailable -Nameet Get-Module -Nameêtre très prudent, avant d'exécuter d'autres fonctions / applets de commande. Et s'il est installé à partir de psgallery ou ailleurs, vous pouvez également exécuter une Find-Moduleapplet de commande pour voir s'il existe une nouvelle version disponible.

mwtilton
la source
2

Vous pouvez utiliser le Get-InstalledModule

If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
  Write-Host "Module does not exist"
}
Else {
  Write-Host "Module exists"
}
thesagarreddy
la source
Beaucoup de bonnes réponses ici, mais avec cette nouvelle méthode simple, cela devrait probablement être la nouvelle réponse acceptée.
not2qubit le
1
  • Premier test si le module est chargé
  • Puis importez

''

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
}

''

Juliano Barbosa
la source
1

Venant de l'arrière-plan Linux. Je préférerais utiliser quelque chose de similaire à grep, donc j'utilise Select-String. Donc même si quelqu'un n'est pas sûr du nom complet du module. Ils peuvent fournir les initiales et déterminer si le module existe ou non.

Get-Module -ListAvailable -All | Select-String Module_Name(peut faire partie du nom du module)

010 M
la source
1

Voici le code pour vérifier si le module AZ est installé ou non:

$checkModule = "AZ"

$Installedmodules = Get-InstalledModule

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

    "$checkModule is installed "

}

else {

    "$checkModule is not installed"

}
Alkum
la source