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, nous voyons donc Module exists
à la fin, bien que SomeModule
n'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?
Vous pouvez utiliser l'option ListAvailable
de Get-Module
:
if (Get-Module -ListAvailable -Name SomeModule) {
Write-Host "Module exists"
}
else {
Write-Host "Module does not exist"
}
L'option ListAvailable ne fonctionne pas pour moi. Au lieu de cela cela:
if (-not (Get-Module -Name "<moduleNameHere>")) {
# module is not loaded
}
Ou, pour être plus succinct:
if (!(Get-Module "<moduleNameHere>")) {
# module is not loaded
}
Un module peut être dans les états suivants:
Si vous voulez simplement que la chose soit disponible dans une session PowerShell, voici une fonction qui le fera ou la quittera 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
Je reviens sur cela car c'est quelque chose que je viens de regarder et il y a des trucs incorrects dans les réponses (bien que ce soit mentionné dans les commentaires).
Première chose cependant. Les questions initiales demandent comment savoir si un module PowerShell est installé. Nous devons parler du mot installé! Vous n'installez pas de modules PowerShell (de toute façon, vous n'installez pas de logiciel).
Les modules PowerShell sont soit disponibles (c'est-à-dire qu'ils se trouvent sur le chemin du module PowerShell), soit importés (ils sont importés dans votre session et vous pouvez appeler les fonctions contenues). Voici comment vérifier votre chemin de module, au cas où vous voudriez savoir où stocker un module:
$env:psmodulepath
Je dirais qu'il est devenu courant d'utiliser C:\Program Files\WindowsPowerShell\Modules; plus souvent car il est disponible pour tous les utilisateurs, mais si vous souhaitez verrouiller vos modules sur votre propre session, incluez-les dans votre profil. C:\Utilisateurs \% nom d'utilisateur%\Documents\WindowsPowerShell\Modules;
Bon, revenons aux deux états.
Le module est-il disponible (utiliser signifie signifie 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 pour le mot "existe" dans la question initiale).
Get-module -Name <modulename>
Cela retournera soit une charge vide de rien si le module n'est pas importé, soit une description du module sur une ligne si c'est le cas. Comme toujours sur Stack Overflow, essayez les commandes ci-dessus sur vos propres modules.
IMHO, il y a une différence entre vérifier si un module est:
1) installé ou 2) importé:
Pour vérifier si installé:
Option 1: Utilisation de Get-Module
avec le paramètre -ListAvailable
:
If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'}
Else{'Module is NOT installed'}
Option 2: Utiliser l'objet $error
:
$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 de Get-Module
avec le paramètre -Name
(que vous pouvez omettre car il s’agit de toute façon de default):
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)."
}
La version actuelle de Powershell a une fonction Get-InstalledModule
qui convient bien à cet usage (ou du moins elle l’a fait dans mon cas).
Get-InstalledModule
La description
La cmdlet
Get-InstalledModule
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 ErrorAction
de maniè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...
}
Venant de fond 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)
`` `
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
}
`` `
try {
Import-Module SomeModule
Write-Host "Module exists"
}
catch {
Write-Host "Module does not exist"
}
Il convient de souligner que votre cmdlet Import-Module
n'a pas d'erreur de fin. Par conséquent, l'exception n'est pas interceptée. Par conséquent, votre instruction catch ne renverra jamais la nouvelle instruction que vous avez écrite.
D'en haut:
"Une erreur de terminaison arrête l'exécution d'une instruction. Si PowerShell ne gère pas une erreur de terminaison, PowerShell cesse également d'exécuter la fonction ou le script à l'aide du pipeline en cours. Dans d'autres langages, tels que C #, les erreurs de terminaison sont appelées exceptions. Pour plus d'informations sur les erreurs, consultez about_Errors. "
Il devrait être écrit comme:
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 cmdlets suggérées Get-Module -ListAvailable -Name
et Get-Module -Name
pour être extrêmement prudent, avant d'exécuter d'autres fonctions/cmdlets. Et s'il est installé à partir de psgallery ou ailleurs, vous pouvez également exécuter une cmdlet Find-Module
pour voir si une nouvelle version est disponible.
Lorsque j'utilise un module autre que celui par défaut dans mes scripts, j'appelle la fonction ci-dessous. En plus 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)