为 .NET Core 项目 - CSPROJ - 而不是 JSON 项目设置版本号

Posted

技术标签:

【中文标题】为 .NET Core 项目 - CSPROJ - 而不是 JSON 项目设置版本号【英文标题】:Setting the version number for .NET Core projects - CSPROJ - not JSON projects 【发布时间】:2017-09-02 14:38:23 【问题描述】:

这个问题和Setting the version number for .NET Core projects很相似,但又不一样。在撰写本文时使用最新稳定版本的 .NET Core (1.1) 和 VS2017,.NET Core 已从基于 JSON 的项目文件切换到 CSPROJ 文件。

所以 - 我想要做的是设置一个 CI 环境,我希望能够在构建之前修改 something 以用正确的版本号标记我的构建。 p>

如果我使用像这样的旧属性(SharedAssemblyInfo.cs 技巧):

[assembly: AssemblyFileVersion("3.3.3.3")]
[assembly: AssemblyVersion("4.4.4.4")]

在项目的某个地方,我得到了CS0579 - Duplicate 'System.Reflection.AssemblyFileVersionAttribute'CS0579 - Duplicate 'System.Reflection.AssemblyVersionAttribute' 构建时出错。

当深入研究它时,我发现\obj\Debug\netcoreapp1.1中有一个在构建过程中生成的文件(在我构建之前它不存在):

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Package Description")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.99.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.99")]
[assembly: System.Reflection.AssemblyProductAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyTitleAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.1.99.0")]

// Generated by the MSBuild WriteCodeFragment class.

问题 - 我该怎么做? 所以我可以看到这必须以某种方式从项目属性“包页面”中输入的值生成,但我不知道在我的 CI 机器上更改这些值的正确方法是什么。

理想情况下,我希望能够在我的 (Jenkins) CI 脚本中指定所有这些信息,但我会满足于设置版本号。

编辑 - 更多信息 在阅读了第一个答案后,我想明确表示我正在创建服务和 NuGET 包 - 我希望有一种对所有内容进行版本控制的方式,这就像我可以只更新单个文件的旧 JSON 项目.

更新 我正在编写脚本来更改 CSPROJ 文件,在我看来这很 hacky,因为我需要修改的部分看起来像这样......

<PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>netcoreapp1.1</TargetFramework>
 <Version>1.0.7777.0</Version>
 <AssemblyVersion>1.0.8888.0</AssemblyVersion>
 <FileVersion>1.0.9999.0</FileVersion>
 <Company>MyCompany</Company>
 <Authors>AuthorName</Authors>
 <Product>ProductName</Product>
 <Description />
 <Copyright>Copyright © 2017</Copyright>
</PropertyGroup>

所以 - 这里的问题是有多个“PropertyGroup”元素;其他人似乎被贴上了标签——但不知道 CSPROJ 是如何组合在一起的,我不能说这种情况总是如此。

我的工作前提是始终填写包详细信息,否则 XML 中不会出现值标签(上图) - 所以我可以使用脚本来更新适当的值。如果值标签不存在,我将不清楚要将值插入哪个 PropertyGroup 元素(以及哪个顺序,因为这似乎很重要;更改顺序阻止了我在 VS2017 中加载项目)。

我仍在坚持寻找比这个更好的解决方案!

更新:在有人将此问题标记为可能重复 (Auto Versioning in Visual Studio 2017 (.NET Core)) 之后 - 我之前没有见过这个问题,现在阅读它似乎几乎相同,只是我不想设置版本号。此外,这个问题的答案并不能解决我的问题 - 只问我在我的问题中提出的问题。我的问题被接受的答案正是我需要解决我的问题的答案 - 所以虽然另一个问题首先出现并且看起来相同 - 它根本对我没有帮助。也许一个模组可以提供帮助?

【问题讨论】:

Auto Versioning in Visual Studio 2017 (.NET Core)的可能重复 更新的答案包括解释 - 我没有看到那个帖子;它似乎是相同的,但它没有回答我的问题。这篇文章的公认答案完美地回答了我的问题。 【参考方案1】:

您可以通过将/p:PropertyName=Value 作为参数传递给dotnet restoredotnet builddotnet pack 来覆盖命令行中的任何属性。

目前,版本组合的工作方式如下: 如果未设置 Version,请使用 VersionPrefix(如果未设置,则默认为 1.0.0)并 - 如果存在 - 附加 VersionSuffix

所有其他版本都默认为 Version 是什么。

因此,例如,您可以在您的 csproj 中设置 &lt;VersionPrefix&gt;1.2.3&lt;/VersionPrefix&gt;,然后调用 dotnet pack --version-suffix beta1 以生成 YourApp.1.2.3-beta1.nupkg(如果您有想要应用版本后缀的项目引用,则需要调用dotnet restore /p:VersionSuffix=beta1 之前 - 这是工具中的一个已知错误)。

当然,您也可以使用自定义变量,请参阅this GitHub issue 了解一些示例。

对于支持的程序集属性的完整参考,我建议查看构建逻辑的源代码here($() 包围的值是使用的属性)。 由于我已经在谈论源,this 是构成版本和其他一些属性的逻辑。

【讨论】:

/p: 参数可能是我正在寻找的;我读到这是 .NET Core 1.1 版本中的新功能,它将参数直接传递给 dotnet msbuild(这也是 .NET Core 1.1 中的新功能)。我将不得不在周末玩一会儿,看看它是否能给我想要的结果,但看起来很有希望。 刚开始尝试这个,正是传递给dotnet msbuild 命令的/p: 参数对我有用。谢谢! 确保在调用多个dotnet 命令时将这些版本参数传递给每个命令。许多命令(如test)将重新构建您的程序集。在我的情况下,我运行build,然后运行test,但没有将我的版本参数传递给test 命令,所以我的版本被清除了。在我的情况下,我在test 命令中添加了--no-build 选项,因此它没有重建。 "如果您有项目引用也希望应用版本后缀,则需要在此之前调用 dotnet restore /p:VersionSuffix=beta1 - 这是工具中的一个已知错误" @Martin 你能提供那个错误的参考吗?【参考方案2】:
dotnet build /p:AssemblyVersion=1.2.3.4

这对你有用吗?

【讨论】:

确实如此,但是这个答案与这个问题的已接受答案(4 个月前发布)有何不同或添加任何内容? 它更简洁 - 但上面的答案根本没有提到设置 AsemblyVersion 属性。它继续关于 VersionPrefix 和 VersionSuffix 以及编辑 csproj 文件等,提到您可以从命令行设置您想要的任何属性,但没有给出您用来完成请求结果的实际命令行。我偶然发现了这个 SO 寻找我最终找到的答案 - 但在这里没有找到。 感谢 McKenzie 先生给了我清晰简洁的答案,我必须向下滚动才能找到! :) 我喜欢一个衬垫。谢谢! 并添加 -p:FileVersion=1.2.3.4 以获取文件资源管理器 -> 属性中显示的其他参数。谢谢!点赞!【参考方案3】:

在我的例子中,主键是/property:Version=1.2.3.4。以下命令行完成了这项工作:

dotnet build SolutionName.sln -c Release /property:Version=1.2.3.4

这将覆盖程序集默认版本。

【讨论】:

但是你的构建服务器不是总是需要知道它的版本吗?如果您从 csproj 编写它,那么开发人员可以在那里更改版本。 @Sinaesthetic 确实如此,但也存在需要使用命令行更新版本的情况。【参考方案4】:

对于那些寻找不同的自动化 (CI) 方法来执行此操作的人,请考虑在 .csproj 文件中基于环境变量使用条件。例如,您通常可能有一个硬编码的版本前缀和一个基于时间戳的后缀。但是对于正确的版本,您可能希望将两者都替换为您在 CI 构建期间设置的单个版本。为此,您可以在调用dotnet build 之前设置一个环境变量:比如说RELEASE_VERSION

在 .csproj 文件的 &lt;PropertyGroup&gt; 下,您将拥有以下内容:

<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.1</VersionPrefix>
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>

上述条件设置为,如果环境变量RELEASE_VERSION为空,则使用正常的前缀和后缀标签。但如果不为空,则使用符号版本标签。

【讨论】:

这个 IMO 是迄今为止最好的解决方案。【参考方案5】:

直接回答您的问题:用于 msbuild 的新 SDK 会自动生成程序集信息文件。您可以使用 msbuild 指令抑制它(通过示例查看它:在基于 project.json 的项目上调用 dotnet migrate)。

但是让我告诉你我的处理方式:我有多个项目共享同一个版本。我添加了一个version.props 文件,其中包含一个属性组,其中包括一个名为VersionPrefix 的项目。我通过 csproj 文件(Include 声明)包含了这个文件。我还删除了所有 AssemblyInfo.cs 文件,让 SDK 为我生成它们。

我在构建过程中修改了version.props 文件。

【讨论】:

仅供参考,如果您在目录层次结构中创建一个名为 Directory.build.props 的文件,它将自动导入,您不需要 &lt;Import /&gt; 指令。 太棒了。谢谢。 +1:它也是一个有用的答案,但我选择了@MartinUllrich 的答案,因为(对我而言)构建命令行比修改文件更容易这一切都在一个最小的 Linux 环境中完成。 这里是一个描述 Directory.Build.props docs.microsoft.com/en-us/visualstudio/msbuild/…的链接【参考方案6】:

如果您在项目文件中缺少它们,MsBuild 2017 将生成一些程序集信息。

如果您可以阅读 msbuild 目标文件,您可以查看:

[VS Install Dir] \MSBuild\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.GenerateAssemblyInfo.targets

您将看到您可以使用项目文件中的某些属性来禁用生成的程序集信息,以防止与您生成的工具重复。

&lt;GenerateAssemblyInfo&gt;(此属性将打开/关闭所有生成程序集信息) &lt;GenerateAssemblyCompanyAttribute&gt; &lt;GenerateAssemblyConfigurationAttribute&gt; &lt;GenerateAssemblyCopyrightAttribute&gt; &lt;GenerateAssemblyDescriptionAttribute&gt; &lt;GenerateAssemblyFileVersionAttribute&gt; &lt;GenerateAssemblyInformationalVersionAttribute&gt; &lt;GenerateAssemblyProductAttribute&gt; &lt;GenerateAssemblyTitleAttribute&gt; &lt;GenerateAssemblyVersionAttribute&gt; &lt;GenerateNeutralResourcesLanguageAttribute&gt;

【讨论】:

【参考方案7】:

我使用 Jenkins + Octopus 进行 CI,以下效果很好:

    有一个预构建 Powershell 脚本,可以将 CI 构建号作为参数或默认为预设值。 在 CI 项目中有一个单独的 nuspec 文件。 预构建脚本将使用最新的构建版本更新 nuspec 文件。 使用 Jenkins 发布项目。 使用#2 中的nuspec 文件手动调用Nuget。 将nuget包推送到八达通。

【讨论】:

nuspec 文件只适用于包吗?我不打算打包所有东西——我正在创建业务线微服务,这些微服务最终将在 Linux 环境中执行(可能在 docker 容器中)。无论如何,如果 nuspec 只是标记 NuGet 包,那么这不是我想要的(尽管它很有用)。 没问题,你还是教了我一些东西,所以点赞:)【参考方案8】:

我在 .csproj 中做的是这个

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <Deterministic>false</Deterministic>
    <AssemblyVersion>2.0.*</AssemblyVersion>
  </PropertyGroup>
</Project>

在 AssemblyVersion 中指定通配符,然后关闭 Deterministic 标志。将为通配符添加数字。

【讨论】:

后来我得到了带有GetType().Assembly.GetName().Version.ToString()的版本。来源:link【参考方案9】:

正如我已经回答 here 一样,我制作了一个名为 dotnet-setversion 的 CLI 工具,您可以使用它来对 *.csproj 样式的 .NET Core 项目进行版本控制。

在 CI 构建期间,您可以使用 GitVersion 或其他工具来确定项目的版本号,然后在项目根目录中调用 dotnet-setversion $YOUR_VERSION_STRING

【讨论】:

它非常聪明,但我可能不明白当你可以将/p: 参数传递给dotnet msbuild 时你为什么要使用它,这将按照接受的答案中的建议完成工作这个问题?查看源代码,这看起来只是更新了 'Version' 元素。 @Jay 我什至不知道它的存在。 "/p" 标志在 1.1.0 中似乎是新的。如果你运行dotnet &lt;command&gt; --help,它甚至都没有提到标志。我赞成接受的答案。 另外,它只更新Version 元素,因为这就是所有需要的(你也可以包含后缀信息)。如果设置Version,则不需要设置VersionSuffixVersionPrefix 哦,别等了,我瞎了哈哈。在命令帮助的底部:“其他参数:应传递给 MSBuild 的任何额外选项。有关可用选项,请参阅 'dotnet msbuild -h'。” 是的,我用它来设置版本、公司名称、产品等...它真的很有用:)【参考方案10】:

将 /p:PropertyName=Value 作为参数传递对我不起作用(ASP.Net Core 2.0 Web App)。 我在 marketpace 上找到了 Manifest Versioning Build Tasks:https://marketplace.visualstudio.com/items?itemName=richardfennellBM.BM-VSTS-Versioning-Task

【讨论】:

我正在使用 .NET Core 2.0 应用程序来使用它——它对我有用。您能否扩展您的答案以显示您正在使用的实际 MSbuild 命令?

以上是关于为 .NET Core 项目 - CSPROJ - 而不是 JSON 项目设置版本号的主要内容,如果未能解决你的问题,请参考以下文章

在 nuget 包中包含引用的项目 DLL [.Net Core RC3 *.csproj 文件]

如何使用 csproj 多目标 .NET Core 类库?

.NET Core - 构建项目指定 ReferencePath

.NET Core项目从xproj+project.json向csproj迁移简介

.net core 项目如何知道构建时要包含哪些文件

[.NET Core 24]把project.json迁移到.csproj