如何检查是否安装了PowerShell模块?

Kle*_*ler 65 powershell

要检查模块是否存在,我尝试了以下方法:

try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}
Run Code Online (Sandbox Code Playgroud)

输出是:

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
Run Code Online (Sandbox Code Playgroud)

我确实得到了一个错误,但没有抛出任何异常,所以我们Module exists最终看到,虽然SomeModule不存在.

是否有一种好方法(最好不会产生错误)来检测系统上是否安装了PowerShell模块?

Kle*_*ler 96

您可以使用以下ListAvailable选项Get-Module:

if (Get-Module -ListAvailable -Name SomeModule) {
    Write-Host "Module exists"
} 
else {
    Write-Host "Module does not exist"
}
Run Code Online (Sandbox Code Playgroud)

  • 我打算建议: Import-Module NonexistingModule -ErrorAction SilentlyContinue IF($error){Write-Host '模块不存在'} ELSE{Write-Host '模块确实存在'} 但你的方式更好,更优雅:) (2认同)

kar*_*zza 25

ListAvailable选项对我不起作用.相反,这样做:

if (-not (Get-Module -Name "<moduleNameHere>")) {
    # module is not loaded
}
Run Code Online (Sandbox Code Playgroud)

或者,更简洁:

if (!(Get-Module "<moduleNameHere>")) {
    # module is not loaded
}
Run Code Online (Sandbox Code Playgroud)

  • 使用`-ListAvailable`时出了什么问题? (6认同)
  • 你检查模块LOADED(它本身是否有用-http://www.systemcentercentral.com/powershell-tip-how-to-load-if-a-module-is-loaded-before-attempting-import-module- 3 /),但不是其他答案检查模块是否存在. (2认同)
  • @KolobCanyon`!`是`-not`的别名,但是我一般不建议在ps1脚本中使用别名。@GaTechThomas它也具有不同的行为,如@MichaelFreidgeim所指定(它不会为已安装但未导入的模块返回真实值)。 (2认同)

Rod*_*Rod 13

模块可以处于以下状态:

  • 进口
  • 在磁盘(或本地网络)上可用
  • 可在在线图库中找到

如果您只是想在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
Run Code Online (Sandbox Code Playgroud)

  • 这是很棒的“一体化”解决方案(我只更改了 Load-Module 以返回 $true/$false 而不是 EXIT) (2认同)

TJ *_*ama 13

当我在脚本中使用非默认模块时,我调用下面的函数。除了模块名称,您还可以提供最低版本。

# 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 -lt $_.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
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

Install-ModuleIfNotInstalled 'CosmosDB' '2.1.3.528'
Run Code Online (Sandbox Code Playgroud)

请让我知道它是否有用(或没有)


mel*_*ous 12

您可以使用 Get-InstalledModule

If (-not(Get-InstalledModule SomeModule -ErrorAction silentlycontinue)) {
  Write-Host "Module does not exist"
}
Else {
  Write-Host "Module exists"
}
Run Code Online (Sandbox Code Playgroud)

  • 这里有很多好的答案,但是使用这种新的简单方法,这可能应该是新的公认答案。 (2认同)
  • 仅当安装了“PowerShellGet”时才有效。在某些气隙服务器上,情况并非如此。 (2认同)

Nig*_*888 11

当前版本的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...
}
Run Code Online (Sandbox Code Playgroud)

  • `Get-InstalledModule` 仅考虑通过 `Install-Module` 安装的模块,`Get-Module -List` 将考虑所有可用模块,无论它们是如何安装的 (4认同)

byt*_*kie 10

只是重新审视这个,因为它是我刚刚遇到的东西,答案中有一些不正确的东西(尽管在评论中提到过).

但第一件事.原始问题询问如何判断是否安装了PowerShell模块.我们需要谈谈安装这个词!您不安装PowerShell模块(不是以传统的方式安装软件).

PowerShell模块可用(即它们位于PowerShell模块路径上),或者它们已导入(它们将导入到您的会话中,您可以调用包含的函数).这是检查模块路径的方法,以防您想知道模块的存储位置:

$env:psmodulepath
Run Code Online (Sandbox Code Playgroud)

我认为使用C:\ Program Files\WindowsPowerShell\Modules正变得越来越普遍; 更常见的原因是它可供所有用户使用,但如果您想将模块锁定到自己的会话中,请将它们包含在您的个人资料中.C:\ Users \用户%的用户名%\文件\ WindowsPowerShell \模块;

好吧,回到两个州.

该模块是否可用(使用可用于表示安装在原始问题中)?

Get-Module -Listavailable -Name <modulename>
Run Code Online (Sandbox Code Playgroud)

这会告诉您模块是否可用于导入.

模块是否已导入?(我用它作为原始问题中"存在"一词的答案).

Get-module -Name <modulename>
Run Code Online (Sandbox Code Playgroud)

如果未导入模块,这将返回空载空载,如果是,则返回模块的单行描述.与Stack Overflow一样,请在您自己的模块上尝试上述命令.


小智 7

try {
    Import-Module SomeModule
    Write-Host "Module exists"
} 
catch {
    Write-Host "Module does not exist"
}
Run Code Online (Sandbox Code Playgroud)

应该指出的是,您的 cmdletImport-Module没有终止错误,因此不会捕获异常,因此无论您的 catch 语句如何,都永远不会返回您编写的新语句。

https://learn.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"
}
Run Code Online (Sandbox Code Playgroud)

返回:

nope
Run Code Online (Sandbox Code Playgroud)

如果您确实想彻底了解,您应该添加其他建议的 cmdlet Get-Module -ListAvailable -Name,并Get-Module -Name在运行其他函数/cmdlet 之前格外小心。如果它是从 ps gallery 或其他地方安装的,您还可以运行 cmdletFind-Module来查看是否有可用的新版本。


she*_*nzy 6

您可以使用该#Requires语句(支持来自 PowerShell 3.0 的模块)。

#Requires 语句阻止脚本运行,除非满足 PowerShell 版本、模块、管理单元以及模块和管理单元版本先决条件。

所以在脚本的顶部,只需添加 #Requires -Module <ModuleName>

如果所需的模块不在当前会话中,PowerShell 会导入它们。

如果无法导入模块,PowerShell 会引发终止错误。

  • 请注意,其他人可能认为这是比上面较长的功能更干净的解决方案:如果模块不在当前会话中,这将“导入”模块,但不会从互联网来源安装它。因此,如果您要将其部署到可能已安装或尚未安装该模块的计算机上,您可能需要更长的解决方案。 (2认同)

Edd*_*mar 5

恕我直言,检查模块是否是有区别的:

1) 安装,或 2) 导入:

检查是否已安装:

选项 1:与参数Get-Module一起使用-ListAvailable

If(Get-Module -ListAvailable -Name "<ModuleName>"){'Module is installed'}
Else{'Module is NOT installed'}
Run Code Online (Sandbox Code Playgroud)

选项 2:使用$error对象:

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

检查是否导入:

使用Get-Modulewith-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)."
}
Run Code Online (Sandbox Code Playgroud)


chr*_*ris 5

因为这个问题出现在很多答案中,所以我将其作为单独的答案发布,而不是发表几条评论。请将此视为公共服务公告。

Get-InstalledModule如果您确实想知道某个模块在安装中是否可用,那么基于使用的答案是极其危险的PowerShell仅当模块是从 PowerShellGet 安装时Get-InstalledModule才会报告该模块的存在。

来自 PowerShell 的证据:

PS C:\Users\chris> Get-InstalledModule | Select-Object -Property Name, Version

Name         Version
----         -------
Choco        1.0.0
NTFSSecurity 4.2.6

PS C:\Users\chris> Get-Module | Select-Object -Property Name, Version

Name                            Version
----                            -------
chocolateyProfile               0.0
CimCmdlets                      7.0.0.0
Microsoft.PowerShell.Management 7.0.0.0
Microsoft.PowerShell.Security   7.0.0.0
Microsoft.PowerShell.Utility    7.0.0.0
Microsoft.WSMan.Management      7.0.0.0
PackageManagement               1.4.7
PowerShellGet                   2.2.5
PSReadLine                      2.1.0
Run Code Online (Sandbox Code Playgroud)

没有任何参数Get-InstalledModule可以用来告诉它“显示您现在没有显示的其他模块”。它无法显示任何其他内容。正如您在上面看到的,当我将九个模块导入会话时,它只显示安装了两个模块。

由于这是一个答案,我将在这里添加指导:

  • @Kiemen Schindler 的答案(/sf/answers/2011835871/)是一个很好的答案。正如其他人所指出的,该-ListAvailable参数实际上并未列出所有可用模块。但实际上,我们大多数人可能不太关心,因为如果ListAvailable不返回模块,那么我们就无法使用它,除非我们已经知道如何使用非标准/手动方法加载它,在这种情况下我们不太可能从一开始就寻找它。
  • 如果您需要其他东西,我认为 @TJ Galama 和 @Rod 都提供了很好的脚本供您开始。我认为 @Rod 的函数特别容易阅读,并且如果您只是学习如何管理模块,那么它很有启发性。但是,如果在加载模块之前尝试无缝安装模块时您的互联网连接断开,它仍然可能会失败。
  • 因此,如果您只是想检查模块是否已加载并且只想运行一个命令来检查,那么最好的解决方案(正如其他人指出的那样)是使用Get-Module -ListAvailable. 这是OP可以使用的一个简单示例:
$module = "SomeModule"

if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $module}) {
  Write-Output "Module is installed."
  Import-Module $module
}
else {
  Write-Output "Module is not installed."
}
Run Code Online (Sandbox Code Playgroud)

但是,我并没有重复其他人在上述答案中提供的答案,我的主要观点是:请不要离开此页面,认为这Get-InstalledModule是确定模块是否已安装(可通过名称在本地导入)的可靠方法您的 PowerShell 安装)。它不是。它将为您提供由PowerShellGet安装的模块的名称,但不会您提供任何其他本地安装的模块的名称。