ฉันจะตรวจสอบได้อย่างไรว่าติดตั้งโมดูล 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
ฉันกำลังจะ suggets: Import-Module NonexistingModule -ErrorAction SilentlyContinue IF ($ error) {Write-Host 'Module is ไม่มีอยู่'} ELSE {Write-Host 'Module is there'} แต่วิธีของคุณดีกว่าหรูหรากว่า :)
Erik Blomgren

ใช้งานได้ดี ขอบคุณ. ฉันจะใช้Write-Warning "Module does not exist..." ;Breakแต่คุณได้ทำงานหนักทั้งหมดแล้ว
Craig.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
คุณตรวจสอบว่าโมดูล LOADED (ซึ่งมีประโยชน์โดยตัวมันเอง - systemcentercentral.com/… ) แต่ไม่ใช่คำตอบอื่นจะตรวจสอบว่ามีโมดูลอยู่หรือไม่
Michael Freidgeim

1
สิ่งนี้ดำเนินการเร็วกว่าการใช้ ListAvailable มาก
GaTechThomas

ค่อนข้างแน่ใจว่า!ไม่ทำงานใน powershell ขึ้นอยู่กับเวอร์ชัน?
Kolob Canyon

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
นี่เป็นโซลูชัน "all-in-one" ที่ยอดเยี่ยม (ฉันเปลี่ยนเฉพาะ Load-Module เพื่อส่งคืน $ true / $ false แทน EXIT)
Andrzej Martyna

17

Powershell เวอร์ชันปัจจุบันมีGet-InstalledModuleฟังก์ชันที่เหมาะสมกับวัตถุประสงค์นี้ (หรืออย่างน้อยก็ในกรณีของฉัน)

Get-InstalledModule

คำอธิบาย

Get-InstalledModulecmdlet รับโมดูล 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 \% ชื่อผู้ใช้% \ Documents \ WindowsPowerShell \ Modules;

ได้เลยกลับไปที่สองสถานะ

โมดูลมีอยู่หรือไม่ (ใช้เพื่อหมายถึงติดตั้งในคำถามเดิม)

Get-Module -Listavailable -Name <modulename>

สิ่งนี้จะบอกคุณว่าโมดูลพร้อมสำหรับการนำเข้าหรือไม่

นำเข้าโมดูลหรือไม่ (ฉันใช้คำนี้เป็นคำตอบสำหรับคำว่า 'มีอยู่' ในคำถามเดิม)

Get-module -Name <modulename>

สิ่งนี้จะส่งคืนภาระว่างเปล่าหากไม่ได้นำเข้าโมดูลหรือคำอธิบายหนึ่งบรรทัดของโมดูลหากเป็นเช่นนั้น เช่นเคยใน Stack Overflow ลองใช้คำสั่งด้านบนในโมดูลของคุณเอง


1
คุณสามารถติดตั้งโมดูลใน PowerShell PowerShellGet มีคำสั่งGet-InstalledModuleที่ไม่ส่งคืนผลลัพธ์เดียวกันกับGet-Module -ListAvailable
Igor

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

ควรชี้ให้เห็นว่า cmdlet ของคุณ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

และหากคุณต้องการที่จะละเอียดถี่ถ้วนคุณควรเพิ่ม cmdlet อื่น ๆ ที่แนะนำGet-Module -ListAvailable -NameและGet-Module -Nameระมัดระวังเป็นพิเศษก่อนที่จะเรียกใช้ฟังก์ชัน / cmdlet อื่น ๆ และหากติดตั้งจาก psgallery หรือที่อื่นคุณสามารถเรียกใช้Find-Modulecmdlet เพื่อดูว่ามีเวอร์ชันใหม่หรือไม่


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"

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.