Azure DevOps流水线自定义产品版本被.csproj覆盖,求类似TFS方案
解决Azure DevOps YAML流水线中产品版本被.csproj覆盖的问题
问题背景
我需要按以下规则设置产品版本:
- 主版本:1
- 次版本:0
- 修订版本:构建日期(格式YYYYMMDD)+ 当日构建次数(1、2、3…)
期望格式示例:1.0.20240708.1
但在Azure DevOps YAML流水线执行后,设置的版本被.csproj文件覆盖。我使用的构建命令如下:
- name: MSBuildArguments value: '/p:OutputPath="$(PackagePath)" /p:ProductVersion="$(ProductVersion)" /p:FileVersion="$(fileVersion)" /p:Copyright="$(CopyrightText)" /p:ProductName="$(productname)"'
通过Write-Output输出的版本值是正常的,但流水线执行后生成的却是随机值。之前在TFS里有内置属性可以实现这个需求,现在想在Azure DevOps中找到类似方案。当前我的版本变量定义如下:
- name: majorVersion value: 1 - name: minorVersion value: 0 - name: buildDate value: $[format('{0:yyyyMMdd}', pipeline.startTime)] - name: buildCounter value: $[counter('BuildCounter', 1)]
$ProductVersion = "$majorVersion.$minorVersion.$buildDate.$buildCounter"
核心问题分析
- .csproj文件中如果硬编码了
<Version>或<ProductVersion>节点,MSBuild执行时会优先使用项目文件内的值,覆盖命令行传入的参数。 - 原
counter函数是全局计数,无法实现“当日构建次数从1开始自增”的需求。
解决步骤
1. 移除.csproj中的硬编码版本
打开项目的.csproj文件,删除或注释掉硬编码的版本节点,让MSBuild优先读取命令行参数:
<!-- 注释掉硬编码版本项 --> <!-- <Version>1.0.0.0</Version> --> <!-- <ProductVersion>1.0.0.0</ProductVersion> --> <!-- <FileVersion>1.0.0.0</FileVersion> -->
2. 调整计数器实现当日自增
修改buildCounter的定义,用当日日期作为计数器的唯一键,确保每天的构建从1开始计数:
- name: majorVersion value: 1 - name: minorVersion value: 0 - name: buildDate value: $[format('{0:yyyyMMdd}', pipeline.startTime)] # 结合日期生成当日专属计数器,实现每日重置计数 - name: buildCounter value: $[counter(format('BuildCounter_{0:yyyyMMdd}', pipeline.startTime), 1)]
3. 正确传递版本变量到流水线上下文
在PowerShell步骤中生成版本号后,需将其设置为流水线环境变量,确保后续MSBuild步骤能读取到:
$ProductVersion = "$($env:majorVersion).$($env:minorVersion).$($env:buildDate).$($env:buildCounter)" $fileVersion = $ProductVersion # 若FileVersion与ProductVersion一致,可直接复用 # 将变量注入流水线上下文 Write-Host "##vso[task.setvariable variable=ProductVersion]$ProductVersion" Write-Host "##vso[task.setvariable variable=fileVersion]$fileVersion"
4. 优化MSBuild参数传递
移除版本变量的额外引号,避免解析错误:
- name: MSBuildArguments value: '/p:OutputPath="$(PackagePath)" /p:ProductVersion=$(ProductVersion) /p:FileVersion=$(fileVersion) /p:Copyright="$(CopyrightText)" /p:ProductName="$(productname)"'
额外注意事项
- 若使用.NET Core/.NET 5+项目,直接传递
/p:Version=$(ProductVersion)即可覆盖项目版本,无需区分ProductVersion和FileVersion。 - 若需保留.csproj中的基础版本框架,可改为
<Version>$(majorVersion).$(minorVersion)</Version>,后续通过命令行补充修订部分,但需确保变量能传递到MSBuild上下文。
内容的提问来源于stack exchange,提问作者beena
相关产品推荐
相关产品推荐

