Azure DevOps下.NET MAUI应用自动版本化:Patch号重置与格式问题
解决方案:Azure DevOps管道中.NET MAUI应用版本自动管理
问题原因分析
- 计数器不重置:你定义
buildNumber时使用的是初始固定值'will be filled in later'作为计数器键,这个值不会随csproj中的版本修改而变化,因此计数器始终基于同一个键,自然不会重置。 - 版本号带空格:大概率是从csproj读取的
ApplicationDisplayVersion包含前后空格,或者脚本拼接时未做格式处理。
方案一:使用管道模板预提取版本号(推荐)
利用Azure DevOps管道模板在初始化阶段从csproj中提取Major.Minor版本,以此作为计数器的键,实现Patch号随主/次版本变更自动重置。
- 创建版本管理模板文件
version-template.yml:
parameters: # 传入csproj文件的路径 csprojPath: '' variables: # 从csproj中提取Major.Minor版本(自动去除前后空格) - name: majorMinorVersion value: $[replace(readFile('${{ parameters.csprojPath }}'), '(?s).*<ApplicationDisplayVersion>\s*(.*?)\s*</ApplicationDisplayVersion>.*', '$1')] # 以Major.Minor为计数器键,主/次版本变更时Patch重置为0 - name: patchVersion value: $[counter(variables['majorMinorVersion'], 0)] # 组合完整的Display Version - name: fullDisplayVersion value: '${{ variables.majorMinorVersion }}.${{ variables.patchVersion }}'
- 在主管道中引用该模板:
# 引用当前仓库的模板 resources: repositories: - repository: self extends: template: version-template.yml parameters: csprojPath: './MyApp/MyApp.csproj' variables: # 保留原有的Version Code计数器 - name: versionCode value: $[counter('versionCode', 1)] steps: # 验证生成的版本号 - task: PowerShell@2 inputs: targetType: 'inline' script: | Write-Host "完整Display Version: $(fullDisplayVersion)" Write-Host "Version Code: $(versionCode)" # 后续构建、签名、发布步骤,传入自动生成的版本号 - task: DotNetCoreCLI@2 inputs: command: 'build' projects: './MyApp/MyApp.csproj' arguments: '/p:ApplicationDisplayVersion=$(fullDisplayVersion) /p:ApplicationVersion=$(versionCode)'
方案二:PowerShell脚本手动维护Patch号(无需模板)
如果不想使用模板,可以通过脚本查询历史构建记录,根据Major.Minor版本自动计算Patch号:
variables: - name: versionCode value: $[counter('versionCode', 1)] steps: # 第一步:从csproj提取Major.Minor版本(去除空格) - task: PowerShell@2 name: getMajorMinor inputs: targetType: 'inline' script: | $xml = [Xml](Get-Content ./MyApp/MyApp.csproj) $majorMinor = $xml.Project.PropertyGroup.ApplicationDisplayVersion.Trim() Write-Host "##vso[task.setvariable variable=majorMinor;isoutput=true]$majorMinor" # 第二步:查询历史构建,计算Patch号 - task: PowerShell@2 name: calculatePatch inputs: targetType: 'inline' script: | # 获取当前流水线的历史构建记录 $builds = az pipelines build list --project $(System.TeamProject) --definition-name $(Build.DefinitionName) --query "[?contains(tags, 'MajorMinor:$(getMajorMinor.majorMinor)')]" | ConvertFrom-Json # 提取历史Patch号,最大值加1;无历史则设为0 if ($builds.Count -gt 0) { $maxPatch = ($builds | ForEach-Object { $_.tags -match 'Patch:(\d+)'; $matches[1] } | Measure-Object -Maximum).Maximum $patch = [int]$maxPatch + 1 } else { $patch = 0 } # 组合完整版本号并设置为输出变量 $fullVersion = "$(getMajorMinor.majorMinor).$patch" Write-Host "##vso[task.setvariable variable=fullDisplayVersion;isoutput=true]$fullVersion" # 给当前构建打标签,方便后续查询 Write-Host "##vso[build.addbuildtag]MajorMinor:$(getMajorMinor.majorMinor)" Write-Host "##vso[build.addbuildtag]Patch:$patch" # 验证版本号 - task: PowerShell@2 inputs: targetType: 'inline' script: | Write-Host "完整Display Version: $(calculatePatch.fullDisplayVersion)" Write-Host "Version Code: $(versionCode)" # 后续构建步骤传入版本号 - task: DotNetCoreCLI@2 inputs: command: 'build' projects: './MyApp/MyApp.csproj' arguments: '/p:ApplicationDisplayVersion=$(calculatePatch.fullDisplayVersion) /p:ApplicationVersion=$(versionCode)'
版本号空格问题的额外处理
无论使用哪种方案,都需要确保从csproj读取的版本号无多余空格:
- 在PowerShell脚本中添加
.Trim()方法去除前后空格; - 检查csproj文件中
ApplicationDisplayVersion标签的内容,确保格式为X.X(无空格)。
内容的提问来源于stack exchange,提问作者Mathias Peene
相关产品推荐
相关产品推荐

