Wie überprüfe ich, ob ein PowerShell-Modul installiert ist?

90

Um zu überprüfen, ob ein Modul vorhanden ist, habe ich Folgendes versucht:

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

Die Ausgabe ist:

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

Ich bekomme eine Fehlermeldung, aber es wird keine Ausnahme ausgelöst, so dass wir Module existsam Ende sehen, obwohl SomeModulees keine gibt.

Gibt es eine gute Möglichkeit (vorzugsweise ohne Fehler zu generieren) festzustellen, ob ein PowerShell-Modul auf dem System installiert ist?

Klemens Schindler
quelle

Antworten:

116

Sie können die ListAvailableOption verwenden Get-Module:

if (Get-Module -ListAvailable -Name SomeModule) {
    Write-Host "Module exists"
} 
else {
    Write-Host "Module does not exist"
}
Klemens Schindler
quelle
1
Ich wollte vorschlagen: Import-Modul NonexistingModule -ErrorAction SilentlyContinue IF ($ error) {Write-Host 'Modul existiert nicht'} ELSE {Write-Host 'Modul existiert'} Aber dein Weg ist besser, eleganter :)
Erik Blomgren
Das funktioniert super. Vielen Dank. Ich werde verwenden Write-Warning "Module does not exist..." ;BreakAber du hast die ganze harte Arbeit gemacht.
Craig.C
Wenn Sie Bibliotheken mit Import-Moduleund einer benutzerdefinierten DLL-Datei importieren , verwenden Sie die -ListAvailableOption nicht, um festzustellen, ob das Modul installiert ist, da es nicht aufgelistet wird. Gemäß der PowerShell 6-Dokumentation gibt "ListAvailable keine Informationen zu Modulen zurück, die nicht in der Umgebungsvariablen PSModulePath enthalten sind, selbst wenn diese Module in der aktuellen Sitzung geladen werden".
Dave F
Dies bestimmt nicht, ob ein Modul installiert wurde (dh Import-Module), sondern bestimmt nur, ob das Modul sofort zur Installation verfügbar ist, ohne einen bestimmten Ort anzugeben, der noch nicht vorhanden ist$env:PSModulePath
Slogmeister Extraordinaire
35

Die Option ListAvailable funktioniert bei mir nicht. Stattdessen tut dies:

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

Oder um es kurz zu machen:

if (!(Get-Module "<moduleNameHere>")) {
    # module is not loaded
}
karezza
quelle
@ oɔɯǝɹ Ich dachte, -ListAvailable ist einfach nicht verfügbar, aber ich habe immer noch Import-Module ausprobiert. Mit Get-Module ist es in Ordnung
Craig.C
2
Sie prüfen, ob das Modul geladen ist (was für sich genommen nützlich ist - systemcentercentral.com/… ), aber nicht die andere Antwort prüft, ob das Modul vorhanden ist.
Michael Freidgeim
1
Dies wird viel schneller ausgeführt als mit ListAvailable.
GaTechThomas
Ziemlich sicher, !dass es in Powershell je nach Version nicht funktioniert?
Kolob Canyon
2
@KolobCanyon !ist ein Alias ​​für -not, aber ich würde die Verwendung von Aliasen in ps1-Skripten im Allgemeinen nicht empfehlen. @GaTechThomas hat auch ein anderes Verhalten, wie von @MichaelFreidgeim angegeben (es gibt keinen Wahrheitswert für installierte, aber nicht importierte Module zurück).
AndreasHassing
26

Ein Modul kann sich in folgenden Zuständen befinden:

  • importiert
  • verfügbar auf der Festplatte (oder im lokalen Netzwerk)
  • verfügbar in der Online-Galerie

Wenn Sie nur das verdammte Ding in einer PowerShell-Sitzung zur Verwendung bereitstellen möchten, finden Sie hier eine Funktion, die dies ausführt oder beendet, wenn dies nicht möglich ist:

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
Stange
quelle
1
Dies ist eine großartige "All-in-One" -Lösung (ich habe nur das Lademodul geändert, um $ true / $ false anstelle von EXIT zurückzugeben)
Andrzej Martyna
17

Die aktuelle Version von Powershell hat eine Get-InstalledModuleFunktion , die diesem Zweck gut entspricht (oder zumindest in meinem Fall).

Get-InstalledModule

Beschreibung

Das Get-InstalledModuleCmdlet ruft PowerShell-Module ab, die auf einem Computer installiert sind.

Das einzige Problem dabei ist, dass eine Ausnahme ausgelöst wird, wenn das angeforderte Modul nicht vorhanden ist. Daher müssen wir ErrorActionentsprechende Einstellungen vornehmen, um diesen Fall zu unterdrücken.

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

    # Install it...
}
NightOwl888
quelle
12

Ich habe dies nur noch einmal durchgesehen, da es etwas ist, mit dem ich gerade konfrontiert wurde, und es gibt einige falsche Dinge in den Antworten (obwohl es in den Kommentaren erwähnt wird).

Das erste aber. In den ursprünglichen Fragen wird gefragt, wie festgestellt werden kann, ob ein PowerShell-Modul installiert ist. Wir müssen über das installierte Wort sprechen! Sie installieren keine PowerShell-Module (ohnehin nicht auf die herkömmliche Weise, wie Sie Software installieren).

PowerShell-Module sind entweder verfügbar (dh sie befinden sich im PowerShell-Modulpfad) oder sie werden importiert (sie werden in Ihre Sitzung importiert und Sie können die enthaltenen Funktionen aufrufen). So überprüfen Sie Ihren Modulpfad, falls Sie wissen möchten, wo ein Modul gespeichert werden soll:

$env:psmodulepath

Ich würde argumentieren, dass es üblich wird, C: \ Programme \ WindowsPowerShell \ Modules zu verwenden. häufiger, da es für alle Benutzer verfügbar ist. Wenn Sie Ihre Module jedoch für Ihre eigene Sitzung sperren möchten, fügen Sie sie in Ihr Profil ein. C: \ Benutzer \% Benutzername% \ Dokumente \ WindowsPowerShell \ Module;

Okay, zurück zu den beiden Staaten.

Ist das Modul verfügbar (mit "verfügbar" bedeutet "in der ursprünglichen Frage installiert")?

Get-Module -Listavailable -Name <modulename>

Hier erfahren Sie, ob ein Modul für den Import verfügbar ist.

Wird das Modul importiert? (Ich verwende dies als Antwort auf das Wort "existiert" in der ursprünglichen Frage).

Get-module -Name <modulename>

Dies gibt entweder eine leere Ladung von nichts zurück, wenn das Modul nicht importiert wird, oder eine einzeilige Beschreibung des Moduls, wenn dies der Fall ist. Probieren Sie wie oben bei Stack Overflow die obigen Befehle auf Ihren eigenen Modulen aus.

Bytejunkie
quelle
1
Sie können das Modul in PowerShell installieren. PowerShellGet hat einen Befehl, Get-InstalledModuleder nicht die gleiche Ausgabe zurückgibt wieGet-Module -ListAvailable
Igor
9

Wenn ich in meinen Skripten nicht standardmäßige Module verwende, rufe ich die folgende Funktion auf. Neben dem Modulnamen können Sie eine Mindestversion angeben.

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

Anwendungsbeispiel:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'

Bitte lassen Sie mich wissen, ob es nützlich ist (oder nicht)

TJ Galama
quelle
4

Sie können die #RequiresAnweisung verwenden (unterstützt Module aus PowerShell 3.0).

Die Anweisung #Requires verhindert, dass ein Skript ausgeführt wird, es sei denn, die PowerShell-Version, Module, Snap-Ins sowie die Voraussetzungen für die Modul- und Snap-In-Version sind erfüllt.

Fügen Sie also oben im Skript einfach hinzu #Requires -Module <ModuleName>

Wenn sich die erforderlichen Module nicht in der aktuellen Sitzung befinden, importiert PowerShell sie.

Wenn die Module nicht importiert werden können, gibt PowerShell einen Beendigungsfehler aus.

sheldonzy
quelle
3

IMHO gibt es einen Unterschied zwischen der Überprüfung, ob ein Modul ist:

1) installiert oder 2) importiert:

So überprüfen Sie, ob installiert:

Option 1: Verwenden Get-Modulemit -ListAvailableParameter:

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

Option 2: Verwenden $error Objekt verwenden:

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

So überprüfen Sie, ob importiert:

Verwenden Get-Modulemit -NameParameter (den Sie weglassen können, da dies ohnehin Standard ist):

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
quelle
3
try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}

Es sollte darauf hingewiesen werden, dass Ihr Cmdlet Import-Module keinen Beendigungsfehler aufweist, daher wird die Ausnahme nicht abgefangen, sodass Ihre catch-Anweisung unabhängig von Ihrer catch-Anweisung niemals die neue Anweisung zurückgibt, die Sie geschrieben haben.

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

Von Oben:

"Ein Beendigungsfehler verhindert, dass eine Anweisung ausgeführt wird. Wenn PowerShell einen Beendigungsfehler nicht auf irgendeine Weise behandelt, beendet PowerShell auch die Ausführung der Funktion oder des Skripts mithilfe der aktuellen Pipeline. In anderen Sprachen, z. B. C #, werden Beendigungsfehler als Ausnahmen bezeichnet Weitere Informationen zu Fehlern finden Sie unter about_Errors. "

Es sollte geschrieben werden als:

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

Welches kehrt zurück:

nope

Und wenn Sie wirklich gründlich sein möchten, sollten Sie die anderen vorgeschlagenen Cmdlets hinzufügen Get-Module -ListAvailable -Nameund Get-Module -Namebesonders vorsichtig sein, bevor Sie andere Funktionen / Cmdlets ausführen. Und wenn es von psgallery oder anderswo installiert wird, können Sie auch ein Find-ModuleCmdlet ausführen, um zu prüfen, ob eine neue Version verfügbar ist.

mwtilton
quelle
2

Du kannst den ... benutzen Get-InstalledModule

If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
  Write-Host "Module does not exist"
}
Else {
  Write-Host "Module exists"
}
thesagarreddy
quelle
Viele gute Antworten hier, aber mit dieser neuen einfachen Methode sollte dies wahrscheinlich die neu akzeptierte Antwort sein.
not2qubit
1
  • Testen Sie zunächst, ob das Modul geladen ist
  • Dann importieren

`` `

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
quelle
1

Ich komme aus Linux. Ich würde es vorziehen, etwas Ähnliches wie grep zu verwenden, daher verwende ich Select-String. Selbst wenn jemand den vollständigen Modulnamen nicht kennt. Sie können die Initialen bereitstellen und bestimmen, ob das Modul vorhanden ist oder nicht.

Get-Module -ListAvailable -All | Select-String Module_Name(kann Teil des Modulnamens sein)

010 M.
quelle
1

Hier ist der Code, um zu überprüfen, ob das AZ-Modul installiert ist oder nicht:

$checkModule = "AZ"

$Installedmodules = Get-InstalledModule

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

    "$checkModule is installed "

}

else {

    "$checkModule is not installed"

}
Alkum
quelle