Azure DevOps YAML中PowerShell更新变量失败求助
解决方案:将Azure DevOps流水线运行号转换为合规的FileVersion
核心问题分析
Windows系统要求FileVersion的四个分段均为uint16类型(0-65535),流水线运行号的yyyyMMdd格式(如20230506)数值远大于该限制,必须拆分后重新组合。另外,Azure DevOps中脚本设置流水线变量需使用特定命令,否则变量无法在后续任务中生效。
步骤1:拆分流水线运行号并设置全局变量
在ci.yml中添加PowerShell任务,拆分Build.BuildNumber并输出可被后续任务读取的变量:
- task: PowerShell@2 displayName: '拆分流水线运行号并设置FileVersion变量' inputs: targetType: 'inline' script: | # 获取流水线运行号,格式示例:20230506.1 $buildNumber = "$(Build.BuildNumber)" # 拆分日期部分和流水号 $datePart = $buildNumber.Split('.')[0] $revision = $buildNumber.Split('.')[1] # 拆分日期为合规分段:年份取后两位+月份,日期+流水号,确保每段≤65535 $versionPart1 = [int]$datePart.Substring(2,2) * 100 + [int]$datePart.Substring(4,2) # 23*100+5=2305 $versionPart2 = [int]$datePart.Substring(6,2) * 100 + [int]$revision # 6*100+1=601 # 输出全局变量,供后续任务使用 Write-Host "##vso[task.setvariable variable=FileVersionPart1;]$versionPart1" Write-Host "##vso[task.setvariable variable=FileVersionPart2;]$versionPart2" # 组合成最终FileVersion格式:主版本.次版本.分段1.分段2 $finalFileVersion = "1.0.$versionPart1.$versionPart2" Write-Host "##vso[task.setvariable variable=FinalFileVersion;]$finalFileVersion"
可选拆分逻辑
如果偏好保留完整年份,可将日期拆分为完整年份和月日+流水号(2023和5061,均≤65535),替换脚本中对应行:
$versionPart1 = $datePart.Substring(0,4) # 2023 $versionPart2 = [int]$datePart.Substring(4,4) * 10 + [int]$revision # 0506*10+1=5061
步骤2:使用Assembly-Info-NetCore@3任务设置FileVersion
在PowerShell任务之后添加该任务,直接引用已设置的全局变量:
- task: Assembly-Info-NetCore@3 displayName: '设置项目FileVersion' inputs: fileNames: '**/*.csproj' fileVersion: '$(FinalFileVersion)' assemblyVersion: '$(FinalFileVersion)' # 可选,同步AssemblyVersion informationalVersion: '$(Build.BuildNumber)' # 可选,保留原始流水线号作为信息版本
步骤3:直接修改.csproj文件的备选方案
如果Assembly-Info-NetCore任务不生效,可直接用PowerShell修改.csproj中的FileVersion节点:
- task: PowerShell@2 displayName: '直接修改csproj的FileVersion' inputs: targetType: 'inline' script: | $csprojFiles = Get-ChildItem -Path "$(Build.SourcesDirectory)" -Filter *.csproj -Recurse $finalFileVersion = "$(FinalFileVersion)" foreach ($file in $csprojFiles) { $xml = [xml](Get-Content $file.FullName) $namespace = $xml.DocumentElement.NamespaceURI # 查找或创建FileVersion节点 $fileVersionNode = $xml.SelectSingleNode("//*[local-name()='FileVersion']", $namespace) if ($fileVersionNode -eq $null) { $propertyGroup = $xml.SelectSingleNode("//*[local-name()='PropertyGroup']", $namespace) $fileVersionNode = $xml.CreateElement("FileVersion", $namespace) $propertyGroup.AppendChild($fileVersionNode) | Out-Null } $fileVersionNode.InnerText = $finalFileVersion $xml.Save($file.FullName) Write-Host "已更新 $($file.FullName) 的FileVersion为 $finalFileVersion" }
关键注意事项
- 设置流水线变量必须使用
Write-Host "##vso[task.setvariable variable=VAR;]VALUE"格式,否则变量仅在当前脚本内部有效。 - 拆分后的每段数值必须确保≤65535,可根据需求调整拆分逻辑。
- 使用Assembly-Info-NetCore任务时,需确保
fileNames路径覆盖所有需要更新的.csproj文件。
内容的提问来源于stack exchange,提问作者kryman27
相关产品推荐
相关产品推荐

