Як перевірити, чи встановлений модуль PowerShell?


92

Щоб перевірити, чи існує модуль, я спробував наступне:

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?


Відповіді:


120

Ви можете скористатися ListAvailableопцією Get-Module:

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

1
Я збирався до цукерок: Імпорт-Модуль NonexistingModule -ErrorAction SilentlyContinue IF ($ error) {Модуль Write-Host не існує '} Інакше {Write-Host' Модуль існує '} Але ваш спосіб кращий, елегантніший :)
Ерік Бломгрен

Це чудово працює. Дякую. Я використаю, Write-Warning "Module does not exist..." ;Breakале ти зробив усю важку роботу.
Крейг. 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” просто недоступний, але я все ще намагався імпортувати модуль. З Get-Module це нормально
Craig.C

2
Ви перевіряєте, чи завантажений модуль (що корисно саме по собі - systemcentercentral.com/… ), але не перевіряє інші відповіді, чи існує модуль.
Michael Freidgeim

1
Це виконується набагато швидше, ніж використання ListAvailable.
GaTechThomas

Цілком впевнений, !що не працює в PowerShell, залежно від версії?
Каньйон Колоба

2
@KolobCanyon !є псевдонімом для -not, але я б не рекомендував використовувати псевдоніми в скриптах ps1 загалом. @GaTechThomas він також має іншу поведінку, як зазначено @MichaelFreidgeim (він не повертає достовірне значення для встановлених, але не імпортованих модулів).
AndreasHassing

27

Модуль може бути у таких станах:

  • імпортні
  • доступний на диску (або локальній мережі)
  • доступно в Інтернет-галереї

Якщо ви просто хочете, щоб ця чортова річ була доступна в сеансі 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)
Анджей Мартина,

17

Поточна версія Powershell має Get-InstalledModuleфункцію, яка добре підходить для цієї мети (або, принаймні, у моєму випадку).

Get-InstalledModule

Опис

Get-InstalledModuleКомандлет отримує модулі 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>

Це поверне порожнє завантаження нічого, якщо модуль не імпортований, або однорядковий опис модуля, якщо він є. Як завжди на Stack Overflow, спробуйте наведені вище команди на власних модулях.


1
Ви можете встановити модуль у PowerShell. PowerShellGet має команду, Get-InstalledModuleяка не повертає той самий результат, що іGet-Module -ListAvailable
Ігор

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

IMHO, існує різниця між перевіркою, чи є модуль:

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-Moduleз -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"
}

Слід зазначити, що ваш командлет Import-Moduleне має помилки завершення, тому виняток не перехоплюється, тому незалежно від того, що ваш оператор catch ніколи не поверне нового написаного вами оператора.

( https://docs.microsoft.com/en-us/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

І якщо ви дійсно хочете бути ретельним, вам слід додати інші запропоновані командлети Get-Module -ListAvailable -Nameта Get-Module -Nameбути дуже обережними, перш ніж запускати інші функції / командлети. І якщо його встановлено з psgallery або деінде, ви також можете запустити Find-Moduleкомандлет, щоб перевірити, чи доступна нова версія.


2

Ви можете використовувати 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"

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.