Aby sprawdzić, czy moduł istnieje, próbowałem wykonać następujące czynności:
try {
Import-Module SomeModule
Write-Host "Module exists"
}
catch {
Write-Host "Module does not exist"
}
Wynik to:
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
Otrzymuję błąd, ale nie jest zgłaszany żaden wyjątek, więc widzimy Module exists
na końcu, chociaż SomeModule
nie istnieje.
Czy istnieje dobry sposób (najlepiej bez generowania błędu) na wykrycie, czy w systemie jest zainstalowany moduł PowerShell?
powershell
Klemens Schindler
źródło
źródło
Odpowiedzi:
Możesz skorzystać z
ListAvailable
opcjiGet-Module
:if (Get-Module -ListAvailable -Name SomeModule) { Write-Host "Module exists" } else { Write-Host "Module does not exist" }
źródło
Write-Warning "Module does not exist..." ;Break
Ale wykonałeś całą ciężką pracę.Import-Module
i niestandardowego pliku dll, nie używaj-ListAvailable
opcji określania, czy moduł jest zainstalowany, ponieważ nie ma go na liście. Zgodnie z dokumentacją programu PowerShell 6 „ListAvailable nie zwraca informacji o modułach, które nie zostały znalezione w zmiennej środowiskowej PSModulePath, nawet jeśli te moduły są ładowane w bieżącej sesji”.Import-Module
) Określa tylko, czy moduł jest natychmiast dostępny do zainstalowania bez określania konkretnej lokalizacji, której jeszcze nie ma$env:PSModulePath
Opcja ListAvailable nie działa dla mnie. Zamiast tego robi to:
if (-not (Get-Module -Name "<moduleNameHere>")) { # module is not loaded }
Lub, aby być bardziej zwięzłym:
if (!(Get-Module "<moduleNameHere>")) { # module is not loaded }
źródło
!
nie działa w PowerShell w zależności od wersji?!
to alias dla-not
, ale generalnie nie polecałbym używania aliasów w skryptach ps1. @GaTechThomas ma również inne zachowanie, określone przez @MichaelFreidgeim (nie zwraca prawdziwej wartości dla zainstalowanych, ale nie zaimportowanych modułów).Moduł może znajdować się w następujących stanach:
Jeśli chcesz po prostu mieć tę cholerną rzecz dostępną w sesji PowerShell do użytku, oto funkcja, która to zrobi lub wyjdzie, jeśli nie może tego zrobić:
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
źródło
Obecna wersja programu Powershell ma
Get-InstalledModule
funkcję, która dobrze pasuje do tego celu (a przynajmniej tak było w moim przypadku).Jedynym problemem jest to, że zgłasza wyjątek, jeśli żądany moduł nie istnieje, więc musimy
ErrorAction
odpowiednio ustawić, aby pominąć ten przypadek.if ((Get-InstalledModule ` -Name "AzureRm.Profile" ` -MinimumVersion 5.0 ` # Optionally specify minimum version to have -ErrorAction SilentlyContinue) -eq $null) { # Install it... }
źródło
Po prostu wracam do tego, ponieważ jest to coś, z czym właśnie się spotkałem, aw odpowiedziach jest trochę niepoprawnych rzeczy (chociaż jest to wspomniane w komentarzach).
Jednak pierwsza rzecz. Oryginalne pytania dotyczą sposobu sprawdzenia, czy moduł programu PowerShell jest zainstalowany. Musimy porozmawiać o słowie zainstalowanym! Nie instalujesz modułów PowerShell (i tak nie w tradycyjny sposób instalujesz oprogramowanie).
Moduły PowerShell są albo dostępne (tj. Znajdują się na ścieżce modułu PowerShell), albo są importowane (są importowane do sesji i można wywołać zawarte w nich funkcje). Oto jak sprawdzić ścieżkę do modułu, jeśli chcesz wiedzieć, gdzie przechowywać moduł:
$env:psmodulepath
Twierdzę, że powszechne jest używanie C: \ Program Files \ WindowsPowerShell \ Modules; częściej, ponieważ jest dostępny dla wszystkich użytkowników, ale jeśli chcesz zablokować moduły do własnej sesji, uwzględnij je w swoim profilu. C: \ Users \% username% \ Documents \ WindowsPowerShell \ Modules;
W porządku, wracając do dwóch stanów.
Czy moduł jest dostępny (używając available to znaczy zainstalowanego w oryginalnym pytaniu)?
Dzięki temu dowiesz się, czy moduł jest dostępny do importu.
Czy moduł jest zaimportowany? (Używam tego jako odpowiedzi na słowo „istnieje” w pierwotnym pytaniu).
Spowoduje to albo zwrócenie pustego obciążenia, jeśli moduł nie jest zaimportowany, lub jednowierszowego opisu modułu, jeśli jest. Jak zawsze w Stack Overflow, wypróbuj powyższe polecenia na swoich własnych modułach.
źródło
Get-InstalledModule
które nie zwraca tego samego wyniku, coGet-Module -ListAvailable
Kiedy używam modułów innych niż domyślne w moich skryptach, wywołuję poniższą funkcję. Oprócz nazwy modułu możesz podać wersję minimalną.
# 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 } } }
przykład użycia:
Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'
Proszę, daj mi znać, czy jest to przydatne (czy nie)
źródło
Możesz użyć
#Requires
instrukcji (obsługuje moduły z programu PowerShell 3.0).Więc u góry skryptu po prostu dodaj
#Requires -Module <ModuleName>
źródło
IMHO, jest różnica między sprawdzeniem, czy moduł jest:
1) zainstalowane lub 2) zaimportowane:
Aby sprawdzić, czy jest zainstalowany:
Opcja 1: Używanie
Get-Module
z-ListAvailable
parametrem:If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'} Else{'Module is NOT installed'}
Opcja 2: Korzystanie z
$error
obiektu:$error.clear() Import-Module "<ModuleName>" -ErrorAction SilentlyContinue If($error){Write-Host 'Module is NOT installed'} Else{Write-Host 'Module is installed'}
Aby sprawdzić, czy zaimportowano:
Używanie
Get-Module
z-Name
parametrem (który możesz pominąć, ponieważ i tak jest domyślny ):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)." }
źródło
try { Import-Module SomeModule Write-Host "Module exists" } catch { Write-Host "Module does not exist" }
Należy zauważyć, że Twoje polecenie cmdlet
Import-Module
nie ma błędu kończącego, dlatego wyjątek nie jest przechwytywany, więc bez względu na to, jaka instrukcja catch nigdy nie zwróci nowej instrukcji, którą napisałeś.( https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6
Z góry:
Powinien być zapisany jako:
Try { Import-Module SomeModule -Force -Erroraction stop Write-Host "yep" } Catch { Write-Host "nope" }
Który zwraca:
A jeśli naprawdę chcesz być dokładny, powinieneś dodać inne sugerowane polecenia cmdlet
Get-Module -ListAvailable -Name
iGet-Module -Name
zachować szczególną ostrożność, zanim uruchomisz inne funkcje / polecenia cmdlet. A jeśli jest zainstalowany z psgallery lub gdzie indziej, możesz również uruchomić polecenieFind-Module
cmdlet, aby sprawdzić, czy jest dostępna nowa wersja.źródło
Możesz użyć
Get-InstalledModule
If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) { Write-Host "Module does not exist" } Else { Write-Host "Module exists" }
źródło
`` ''
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 }
`` ''
źródło
Pochodzący z Linuksa. Wolałbym użyć czegoś podobnego do grep, dlatego używam Select-String. Więc nawet jeśli ktoś nie jest pewien pełnej nazwy modułu. Mogą podać inicjały i określić, czy moduł istnieje, czy nie.
Get-Module -ListAvailable -All | Select-String Module_Name
(może być częścią nazwy modułu)źródło
Oto kod, aby sprawdzić, czy moduł AZ jest zainstalowany, czy nie:
$checkModule = "AZ" $Installedmodules = Get-InstalledModule if ($Installedmodules.name -contains $checkModule) { "$checkModule is installed " } else { "$checkModule is not installed" }
źródło