导入多个版本的 Powershell 模块会加载它们吗?

Importing multiple versions of Powershell Modules loads them all?

导入多个版本的模块(这是PS7):

Import-Module -Name MyModule -RequiredVersion 1.0.28
Import-Module -Name MyModule -RequiredVersion 1.0.29

会将两个版本加载到您的会话中:

Get-Module -Name MyModule 

输出:

ModuleType Version    PreRelease Name
---------- -------    ---------- ---- 
Script     1.0.28                MyModule
Script     1.0.29                MyModule

当您尝试编写 CI/CD 脚本时,这会变得非常混乱,因为有人可能在本地加载了多个版本。就我而言,我想确保在继续之前加载特定版本。

在这种情况下 PS 实际使用哪个版本?是最后加载的版本而不是最高版本吗?

有没有一种简单的方法可以确保使用特定版本,而不是遍历所有其他版本并将其删除?

Which version does PS actually use in this scenario?

最近导入的版本优先Get-Member的输出在reverse中表示 优先顺序(从 PowerShell Core 7.2.0-preview.5 开始);也就是说,给定模块的 Get-Module 输出中列出的 last 版本是有效的版本(对于同名命令)。

对于给定的命令,您可以使用Get-Command查看它来自哪个模块(版本)。[1]

警告:最近导入的版本仅在它隐藏先前导入版本的同名命令的意义上具有优先权.因此,如果先前导入的版本有 附加的 命令未被最近导入的版本定义(不再),它们仍然有效。


Is there an easy way to ensure a specific version is being used, short of looping over all other versions and removing them?

如果要确保不加载其他版本,请使用Remove-Module <name>删除所有[=67] =] 版本的模块 具有来自会话的给定名称。

相比之下,如果你想卸载一个特定的版本,你将传递一个完全合格的模块nameRemove-Module-FullyQualifiedName 参数;例如:

Remove-Module -FullyQualifiedName @{ ModuleName = 'MyModule'; RequiredVersion = '1.0.28' }

注意使用 RequiredVersion 键来指定要卸载的 exact 版本;相比之下,使用键 ModuleVersion 将卸载给定版本 和所有更高版本 .


[1] 请注意,您甚至可以通过使用 -FullyQualifiedModule参数(例如
Get-Command Get-Foo -FullyQualifiedModule @{ ModuleName='Foo'; RequiredVersion='1.0.28' }
),然后您可以使用 &call operator. However, due to the bug detailed in GitHub issue #15298 调用,从 PowerShell Core 7.2.0-preview.5 开始,这仅在目标模块版本被 显式导入时有效 首先(例如,Import-Module Foo -RequiredVersion 1.0.28)。

将我遇到的更多细节添加到 mklement0 的出色回答中:

  • Get-Module returns 每个加载模块版本的 ExportedFunctionsExportedCmdletsExportedCommands 列表。完美!

  • 警惕嵌套模块! Powershell 将分离命名模块的信息,并在您要求的模块的 NestedModules 属性 下列出任何辅助模块。

  • 您可以在 import-module 时指定使用的命令和模块版本,这样您可以比一次性导入整个模块更好地管理 运行 环境。

示例:

# Here I have two versions loaded, but only one has any exported cmdlets:
Get-Module ExchangeOnlineManagement | Format-List Version,ExportedFunctions,ExportedCmdlets,ExportedCommands,NestedModules

Version           : 2.0.4
ExportedFunctions : {[Connect-ExchangeOnline, Connect-ExchangeOnline], …}
ExportedCmdlets   : {[Get-EXOCasMailbox, Get-EXOCasMailbox], …}
ExportedCommands  : {[Get-EXOCasMailbox, Get-EXOCasMailbox], …}
NestedModules     : {Microsoft.Exchange.Management.RestApiClient,
                    Microsoft.Exchange.Management.ExoPowershellGalleryModule}

Version           : 2.0.5
ExportedFunctions : {[Connect-ExchangeOnline, Connect-ExchangeOnline], …}
ExportedCmdlets   : {}
ExportedCommands  : {[Connect-ExchangeOnline, Connect-ExchangeOnline], …}
NestedModules     : {}

# I can see function Connect-ExchangeOnline was loaded twice, so to see which version is active:
Get-Command Connect-ExchangeOnline 

CommandType : Function
Name        : Connect-ExchangeOnline
Version     : 2.0.5
Source      : ExchangeOnlineManagement

# I use this to see current loaded assemblies, and module version should be in the path
[appdomain]::CurrentDomain.GetAssemblies() |
    Where { $_.Modules.FullyQualifiedName.contains('ExchangeOnlineManagement') } |
    Select -ExpandProperty Modules |
    Format-List Name,Assembly,FullyQualifiedName

Name               : Microsoft.Exchange.Management.AdminApiProvider.dll
Assembly           : Microsoft.Exchange.Management.AdminApiProvider, Version=17.0.0.0
FullyQualifiedName : \path\to\Modules\ExchangeOnlineManagement.0.4\netCore\Microsoft.Exch 
                     ange.Management.AdminApiProvider.dll

Name               : Microsoft.Exchange.Management.ExoPowershellGalleryModule.dll
Assembly           : Microsoft.Exchange.Management.ExoPowershellGalleryModule, Version=17.0.0.0
FullyQualifiedName : \path\to\Modules\ExchangeOnlineManagement.0.4\netCore\Microsoft.Exch 
                     ange.Management.ExoPowershellGalleryModule.dll