Bagaimana cara memeriksa apakah modul PowerShell diinstal?

92

Untuk memeriksa apakah ada modul, saya telah mencoba yang berikut ini:

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

Outputnya adalah:

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

Saya mendapatkan kesalahan, tetapi tidak terkecuali dilempar, jadi kita lihat Module existspada akhirnya, meskipun SomeModuletidak ada.

Apakah ada cara yang baik (lebih disukai tanpa menimbulkan kesalahan) untuk mendeteksi jika modul PowerShell diinstal pada sistem?

Klemens Schindler
sumber

Jawaban:

120

Anda dapat menggunakan ListAvailableopsi Get-Module:

if (Get-Module -ListAvailable -Name SomeModule) {
    Write-Host "Module exists"
} 
else {
    Write-Host "Module does not exist"
}
Klemens Schindler
sumber
1
Saya akan suggets: Import-Module NonexistingModule -ErrorAction SilentlyContinue IF ($ error) {Write-Host 'Module tidak ada'} ELSE {Write-Host 'Module is there'} Tapi cara Anda lebih baik, lebih elegan :)
Erik Blomgren
Ini bekerja dengan baik. Terima kasih. Saya akan menggunakan Write-Warning "Module does not exist..." ;BreakTapi Anda telah melakukan semua kerja keras.
Craig.C
Jika Anda mengimpor pustaka menggunakan Import-Moduledan file dll kustom, jangan gunakan -ListAvailableopsi untuk menentukan apakah modul diinstal karena tidak akan terdaftar. Menurut dokumentasi PowerShell 6 , "ListAvailable tidak mengembalikan informasi tentang modul yang tidak ditemukan di variabel lingkungan PSModulePath, bahkan jika modul tersebut dimuat di sesi saat ini".
Dave F
Ini tidak menentukan apakah sebuah modul telah diinstal (yaitu Import-Module) itu hanya menentukan apakah modul segera tersedia untuk diinstal tanpa menentukan lokasi tertentu yang belum ada di$env:PSModulePath
Slogmeister Extraordinaire
34

Opsi ListAvailable tidak berfungsi untuk saya. Sebaliknya ini:

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

Atau, lebih singkatnya:

if (!(Get-Module "<moduleNameHere>")) {
    # module is not loaded
}
karezza
sumber
@ oɔɯǝɹ Saya pikir -ListAvailable tidak tersedia tetapi saya masih mencoba Import-Module. Dengan Get-Module tidak apa
Craig.C
2
Anda memeriksa apakah modul LOADED (yang berguna dengan sendirinya - systemcentercentral.com/… ), tetapi bukan jawaban yang lain memeriksa apakah modul ada.
Michael Freidgeim
1
Ini dijalankan jauh lebih cepat daripada menggunakan ListAvailable.
GaTechThomas
Cukup yakin !tidak berfungsi di PowerShell tergantung pada versinya?
Kolob Canyon
2
@KolobCanyon !adalah alias untuk -not, tetapi saya tidak akan merekomendasikan penggunaan alias dalam skrip ps1 secara umum. @GaTechThomas juga memiliki perilaku yang berbeda, seperti yang ditentukan oleh @MichaelFreidgeim (tidak mengembalikan nilai yang sebenarnya untuk modul yang diinstal, tetapi tidak diimpor).
AndreasHassing
27

Sebuah modul bisa berada dalam status berikut:

  • impor
  • tersedia di disk (atau jaringan lokal)
  • tersedia di galeri online

Jika Anda hanya ingin hal terkutuk tersedia dalam sesi PowerShell untuk digunakan, berikut adalah fungsi yang akan melakukannya atau keluar jika tidak dapat menyelesaikannya:

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
tongkat
sumber
1
ini adalah solusi "all-in-one" yang hebat (saya hanya mengubah Load-Module untuk mengembalikan $ true / $ false alih-alih EXIT)
Andrzej Martyna
17

Versi Powershell saat ini memiliki Get-InstalledModulefungsi yang sesuai dengan tujuan ini dengan baik (atau setidaknya dalam kasus saya).

Get-InstalledModule

Deskripsi

The Get-InstalledModulecmdlet mendapat modul PowerShell yang diinstal pada komputer.

Satu-satunya masalah dengan itu adalah ia melontarkan pengecualian jika modul yang diminta tidak ada, jadi kita perlu menyetel dengan ErrorActiontepat untuk menekan kasus itu.

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

    # Install it...
}
NightOwl888
sumber
13

Hanya meninjau kembali ini karena itu adalah sesuatu yang baru saja saya hadapi dan ada beberapa hal yang salah dalam jawaban (meskipun disebutkan di komentar).

Hal pertama. Pertanyaan asli menanyakan bagaimana cara mengetahui apakah modul PowerShell diinstal. Kita perlu berbicara tentang kata terpasang! Anda tidak menginstal modul PowerShell (tidak dengan cara tradisional Anda menginstal perangkat lunak).

Modul PowerShell tersedia (yaitu mereka berada di jalur modul PowerShell), atau diimpor (mereka diimpor ke sesi Anda dan Anda dapat memanggil fungsi yang ada). Ini adalah cara memeriksa jalur modul Anda, jika Anda ingin tahu di mana menyimpan modul:

$env:psmodulepath

Saya berpendapat bahwa itu menjadi umum untuk menggunakan C: \ Program Files \ WindowsPowerShell \ Modules; lebih sering karena itu tersedia untuk semua pengguna, tetapi jika Anda ingin mengunci modul Anda ke sesi Anda sendiri, sertakan mereka di profil Anda. C: \ Users \% username% \ Documents \ WindowsPowerShell \ Modules;

Baiklah, kembali ke dua negara bagian.

Apakah modul tersedia (menggunakan kata tersedia untuk dipasang di pertanyaan asli)?

Get-Module -Listavailable -Name <modulename>

Ini memberi tahu Anda jika modul tersedia untuk diimpor.

Apakah modul diimpor? (Saya menggunakan ini sebagai jawaban untuk kata 'ada' dalam pertanyaan aslinya).

Get-module -Name <modulename>

Ini akan mengembalikan beban kosong dari apa-apa jika modul tidak diimpor, atau deskripsi satu baris dari modul jika itu. Seperti biasa di Stack Overflow, coba perintah di atas pada modul Anda sendiri.

bytejunkie
sumber
1
Anda dapat memasang modul di PowerShell. PowerShellGet memiliki perintah Get-InstalledModuleyang tidak mengembalikan keluaran yang sama sepertiGet-Module -ListAvailable
Igor
9

Ketika saya menggunakan modul non-default dalam skrip saya, saya memanggil fungsi di bawah ini. Selain nama modul, Anda dapat memberikan versi minimum.

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

contoh penggunaan:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'

Tolong beri tahu saya jika itu berguna (atau tidak)

TJ Galama
sumber
4

Anda dapat menggunakan #Requirespernyataan (mendukung modul dari PowerShell 3.0).

Pernyataan #Requires mencegah skrip berjalan kecuali jika versi PowerShell, modul, snap-in, dan modul serta prasyarat versi snap-in terpenuhi.

Jadi Di bagian atas skrip, cukup tambahkan #Requires -Module <ModuleName>

Jika modul yang diperlukan tidak ada dalam sesi saat ini, PowerShell mengimpornya.

Jika modul tidak dapat diimpor, PowerShell membuat kesalahan penghentian.

sheldonzy
sumber
3

IMHO, ada perbedaan antara memeriksa apakah suatu modul:

1) dipasang, atau 2) diimpor:

Untuk memeriksa apakah sudah terpasang:

Opsi 1: Menggunakan Get-Module dengan -ListAvailableparameter:

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

Opsi 2: Menggunakan $error objek:

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

Untuk memeriksa apakah diimpor:

Menggunakan Get-Modulewith -Nameparameter (yang dapat Anda hilangkan karena defaultnya ):

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

Ini harus ditunjukkan bahwa cmdlet Anda Import-Moduletidak memiliki kesalahan penghentian, oleh karena itu pengecualian tidak tertangkap jadi apa pun pernyataan catch Anda tidak akan pernah mengembalikan pernyataan baru yang telah Anda tulis.

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

Dari atas:

"Kesalahan penghentian menghentikan pernyataan agar tidak berjalan. Jika PowerShell tidak menangani kesalahan penghentian dalam beberapa cara, PowerShell juga berhenti menjalankan fungsi atau skrip menggunakan pipa saat ini. Dalam bahasa lain, seperti C #, kesalahan penghentian disebut sebagai pengecualian . Untuk informasi lebih lanjut tentang kesalahan, lihat about_Errors. "

Ini harus ditulis sebagai:

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

Yang mengembalikan:

nope

Dan jika Anda benar-benar ingin teliti, Anda harus menambahkan cmdlet lain yang disarankan Get-Module -ListAvailable -Namedan Get-Module -Nameekstra hati-hati, sebelum menjalankan fungsi / cmdlet lainnya. Dan jika diinstal dari psgallery atau di tempat lain Anda juga dapat menjalankan Find-Modulecmdlet untuk melihat apakah ada versi baru yang tersedia.

mwtilton.dll
sumber
2

Anda dapat menggunakan Get-InstalledModule

If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
  Write-Host "Module does not exist"
}
Else {
  Write-Host "Module exists"
}
thesagarreddy
sumber
Banyak jawaban bagus di sini, tetapi dengan metode baru yang sederhana ini, ini mungkin jawaban baru yang diterima.
not2qubit
1
  • Tes pertama apakah modul tersebut dimuat
  • Lalu impor

``

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

Berasal dari latar belakang Linux. Saya lebih suka menggunakan sesuatu yang mirip dengan grep, oleh karena itu saya menggunakan Select-String. Begitu pun jika seseorang tidak yakin dengan nama modul lengkapnya. Mereka dapat memberikan inisial dan menentukan apakah modul tersebut ada atau tidak.

Get-Module -ListAvailable -All | Select-String Module_Name(dapat menjadi bagian dari nama modul)

010 M
sumber
1

Berikut adalah kode untuk memeriksa apakah modul AZ dipasang atau tidak:

$checkModule = "AZ"

$Installedmodules = Get-InstalledModule

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

    "$checkModule is installed "

}

else {

    "$checkModule is not installed"

}
Alkum
sumber