Azure DevOps管道因Az.Accounts版本过低失败,如何指定正确版本?
问题说明
执行Invoke-AzCostManagementExecuteReport命令时管道失败,原因是当前会话导入的Az.Accounts版本为2.17.0,低于Az.CostManagement要求的2.19.0。虽然已安装2.19.0版本,但AzurePowerShell@5任务会在自定义脚本执行前自动加载旧版模块,导致会话内无法切换到新版本,报错如下:
This module requires Az.Accounts version 2.19.0. An earlier version of Az.Accounts is imported in the current PowerShell session. Please open a new session before importing this module. This error could indicate that multiple incompatible versions of the Azure PowerShell cmdlets are installed on your system.
##[error]PowerShell exited with code '1'.
原管道配置:
- task: PowerShell@2 displayName: 'Install Az.Accounts' inputs: pwsh: true targetType: 'inline' script: 'Install-Module -Name Az.Accounts -RequiredVersion 2.19.0 -Repository PSGallery -Force - task: AzurePowerShell@5 displayName: 'Export Cost Data' inputs: pwsh: true azureSubscription: $serviceconnection azurePowerShellVersion: LatestVersion scriptType: 'inlineScript' inline: | Update-Module -Name "Az.Accounts" -Force Get-InstalledModule -Name "Az.Accounts" Get-Module -ListAvailable $azTenantId = (Get-AzContext).Tenant.Id Write-host (Get-AzTenant | where-object Id -eq $azTenantId).Name Install-Module Az.CostManagement -Scope CurrentUser -Force Import-Module Az.CostManagement Invoke-AzCostManagementExecuteReport -ExportName $costExport -Scope $scope
解决方案
方法1:改用PowerShell@2任务手动登录并控制模块版本
跳过AzurePowerShell@5的自动模块加载,用PowerShell@2任务手动完成登录和脚本执行,完全掌控模块版本:
- task: PowerShell@2 displayName: 'Execute Cost Export with Specified Az.Accounts' inputs: pwsh: true targetType: 'inline' script: | # 安装指定版本的Az.Accounts和Az.CostManagement Install-Module -Name Az.Accounts -RequiredVersion 2.19.0 -Repository PSGallery -Force -Scope CurrentUser Install-Module -Name Az.CostManagement -Repository PSGallery -Force -Scope CurrentUser # 导入指定版本的Az.Accounts Import-Module -Name Az.Accounts -RequiredVersion 2.19.0 -Force # 用服务连接信息登录Azure $servicePrincipal = ConvertFrom-Json '$(servicePrincipalJson)' Connect-AzAccount -ServicePrincipal -Tenant $servicePrincipal.TenantId -ApplicationId $servicePrincipal.ApplicationId -Credential (New-Object System.Management.Automation.PSCredential($servicePrincipal.ApplicationId, (ConvertTo-SecureString $servicePrincipal.ClientSecret -AsPlainText -Force))) # 执行核心命令 $azTenantId = (Get-AzContext).Tenant.Id Write-host (Get-AzTenant | where-object Id -eq $azTenantId).Name Invoke-AzCostManagementExecuteReport -ExportName $costExport -Scope $scope env: servicePrincipalJson: $(AzureServiceConnectionDetails)
注意:需在管道变量中添加
AzureServiceConnectionDetails,值为目标服务连接的JSON内容(可通过Azure DevOps服务连接的"查看JSON"功能获取)。
方法2:在AzurePowerShell@5任务中强制替换旧模块
在脚本开头卸载已导入的旧版Az.Accounts,再重新导入指定版本:
- task: AzurePowerShell@5 displayName: 'Export Cost Data' inputs: pwsh: true azureSubscription: $serviceconnection azurePowerShellVersion: LatestVersion scriptType: 'inlineScript' inline: | # 卸载已加载的旧版Az.Accounts if (Get-Module -Name Az.Accounts) { Remove-Module -Name Az.Accounts -Force } # 安装并导入指定版本的Az.Accounts Install-Module -Name Az.Accounts -RequiredVersion 2.19.0 -Repository PSGallery -Force -Scope CurrentUser Import-Module -Name Az.Accounts -RequiredVersion 2.19.0 -Force # 验证版本 Get-InstalledModule -Name Az.Accounts Get-Module -Name Az.Accounts # 安装并导入Az.CostManagement Install-Module Az.CostManagement -Scope CurrentUser -Force Import-Module Az.CostManagement -Force # 执行核心命令 $azTenantId = (Get-AzContext).Tenant.Id Write-host (Get-AzTenant | where-object Id -eq $azTenantId).Name Invoke-AzCostManagementExecuteReport -ExportName $costExport -Scope $scope
方法3:使用预配置模块版本的自定义代理池
若频繁遇到版本兼容问题,可创建自定义代理池,在代理机器上预先安装Az.Accounts 2.19.0及对应版本的Az.CostManagement,管道直接使用该代理池,避免每次安装模块的开销。
内容的提问来源于stack exchange,提问作者steveyB

