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


73

此问题与设置.NET Core项目的版本号非常相似,但不相同。在撰写本文(1.1)和VS2017时,使用.NET Core的最新稳定版本,.NET Core已从基于JSON的项目文件切换为CSPROJ文件。

所以-我想要做的是建立一个CI环境,在该环境中,我希望能够在构建之前进行一些修改,以使用正确的版本号标记我的构建。

如果我使用这样的旧属性(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文件的更改的脚本,在我看来,这是很棘手的,因为我需要修改的部分如下所示...

<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中加载项目)。

我仍在寻求比这更好的解决方案!

更新:在有人将此问题标记为可能的重复问题之后(Visual Studio 2017(.NET Core)中的自动版本控制)-我之前从未见过此问题,现在阅读它似乎几乎是相同的,只是我不想设置版本号。另外,此问题的答案不能解决我的问题-仅询问我在问题中提出的内容。我的问题的公认答案恰好是我解决问题所需要的答案-因此,当另一个问题排在第一位并且看起来相同时-根本没有帮助。也许mod可以帮上忙吗?



更新的答案以包含解释-我没有看到该帖子;它似乎是相同的,但不能回答我的问题。这个帖子的公认答案可以完美地回答我的问题。
杰伊

Answers:


86

你可以通过覆盖在命令行的任何财产/p:PropertyName=Value作为参数dotnet restoredotnet builddotnet pack

当前,版本组成按以下方式工作:如果Version未设置,请使用VersionPrefix(如果未设置,则默认为1.0.0),如果存在,则使用-append VersionSuffix

然后将所有其他版本默认为最新版本Version

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

当然,您也可以使用自定义变量,有关一些示例,请参见GitHub问题

有关受支持的程序集属性的完整参考,我建议在此处查看构建逻辑的源代码(包围的值$()是所使用的属性)。并且由于我已经在谈论源代码,因此这是组成版本和其他一些属性的逻辑。


/p:参数可能是什么我要找的; 我读到它是.NET Core 1.1版中的新功能,并将参数直接传递给dotnet msbuild(这也是.NET Core 1.1中的新功能)。周末我将不得不花一点时间来看看它是否能达到我想要的效果,但是看起来很有希望。
杰伊

刚刚尝试了一下,这是/p:传递给dotnet msbuild命令的参数,它对我有用。谢谢!
杰伊

2
如果要调用多个dotnet命令,请确保将这些版本参数传递给每个命令。许多命令(如test)将重新构建程序集。在我的情况下,我正在运行buildtest但没有将我的版本参数传递给test命令,因此我的版本被清除了。在我的情况下,我将--no-build选项添加到了test命令中,因此它没有重建。
亚伦·詹森

“如果您也有想要同时应用版本后缀的项目参考,则需要在此之前调用dotnet restore / p:VersionSuffix = beta1-这是工具中的已知错误” @Martin您可以提供参考吗那个臭虫?
尼尔·巴恩威尔

63
dotnet build /p:AssemblyVersion=1.2.3.4

那对你有用吗?


确实如此,但是此答案与该问题(4个月前发布)的已接受答案有何不同?
杰伊

31
对于一个人来说,它更简洁一些,但是上面的答案根本没有提到设置AsemblyVersion属性。它继续介绍VersionPrefix和VersionSuffix以及编辑csproj文件等,并提到您可以从命令行设置所需的任何属性,但没有提供用于完成请求的结果的实际命令行。我偶然发现了这个问题,寻找最终找到的答案-但在这里找不到。
克里斯·麦肯齐

抱歉,我无法接受,Martin的回答完全覆盖了该问题,该问题指示我检查msbuild命令行参考\源代码,并且,如果您阅读我的问题,(最终更新)我不是只是尝试设置版本号。也许您的帖子可以帮助其他人。
杰伊

5
谢谢McKenzie先生给了我明确的答案,我必须向下滚动才能找到答案!:)
Matt Sanders

4
并添加-p:FileVersion = 1.2.3.4以获取在文件资源管理器->属性中显示的另一个参数。谢谢!已投票!
Ben Butzer

14

就我而言,主键是/property:Version=1.2.3.4。然后以下命令行完成了该工作:

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

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


但是,您的构建服务器不总是必须知道它的版本吗?如果您是通过csproj编写的,则开发人员只需在此处更改版本即可。
Sinaesthetic

@Sinaesthetic是正确的,但是在某些情况下,您需要使用命令行更新版本。
maytham-ɯɐɥʇʎɐɯ

10

对于那些寻求使用其他自动化(CI)方法执行此操作的用户,请考虑根据环境变量在.csproj文件中使用条件。例如,您通常可能具有硬编码的版本前缀和基于时间戳的后缀。但是对于适当的发行版,您希望将其都替换为在CI构建期间设置的单个版本。为此,您可以在调用之前设置环境变量dotnet build:假设,RELEASE_VERSION

在.csproj文件中的下<PropertyGroup>,您将具有以下内容:

<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为空,则使用常规的前缀和后缀标签。但是,如果不为空,则使用签名版本标记。


7

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

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

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


8
如果您创建了一个Directory.build.props在目录层次结构中命名的文件,它将自动导入,并且您不需要<Import />指令。
Martin Ullrich

太棒了 谢谢。
托马斯

2
+1:这也是一个有用的答案,但是我接受了@MartinUllrich的答案,因为(对我来说)建立命令行比修改文件更容易,因为在最小的Linux环境中进行所有操作。
杰伊

这是描述Directory.Build.props docs.microsoft.com/en-us/visualstudio/msbuild
habakuk

5

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

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

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

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

  • <GenerateAssemblyInfo> (此属性将打开/关闭全部生成装配信息)
  • <GenerateAssemblyCompanyAttribute>
  • <GenerateAssemblyConfigurationAttribute>
  • <GenerateAssemblyCopyrightAttribute>
  • <GenerateAssemblyDescriptionAttribute>
  • <GenerateAssemblyFileVersionAttribute>
  • <GenerateAssemblyInformationalVersionAttribute>
  • <GenerateAssemblyProductAttribute>
  • <GenerateAssemblyTitleAttribute>
  • <GenerateAssemblyVersionAttribute>
  • <GenerateNeutralResourcesLanguageAttribute>

4

我将Jenkins + Octopus用于CI,以下操作效果很好:

  1. 拥有一个预构建Powershell脚本,该脚本可以将CI内部版本号作为参数或默认为预设值。
  2. nuspec在CI项目中有一个单独的文件。
  3. 预构建脚本将nuspec使用最新的构建版本更新文件。
  4. 与詹金斯一起发布项目。
  5. Nuget使用nuspec#2中的文件手动调用。
  6. nuget包装推到八达通。

nuspec文件仅适用于软件包吗?我没有计划打包所有东西-我正在创建业务微服务,最终将在Linux环境(可能在docker容器)中执行。无论如何,如果nuspec只是在标记NuGet软件包,那不是我想要的(尽管它很有用)。
杰伊

2
没问题,您仍然教给我一些东西,因此请赞成:)
Jay

1

正如我在这里回答的那样,我制作了一个名为dotnet-setversion的CLI工具,可用于对* .csproj样式的.NET Core项目进行版本控制。

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


1
这非常聪明,但是我可能不明白为什么当您只可以按照接受的问题答案中的建议将/p:参数传递给dotnet msbuild可以执行此工作的参数时,为什么要使用它呢?查看源代码,看起来它只更新了'Version'元素。
杰伊

@周杰伦,我什至不知道它的存在。“ / p”标志似乎在1.1.0中是新的。如果您运行它甚至不会提到该标志dotnet <command> --help。我已对接受的答案进行了投票。
Tagc

另外,它仅更新Version元素,因为这就是所有需要的内容(您也可以在其中包含后缀信息)。如果已设置Version,则无需设置VersionSuffixVersionPrefix
Tagc

哦,不用了,我瞎了哈哈。在命令帮助的底部:“其他参数:应该传递给MSBuild的任何其他选项。有关可用选项,请参见'dotnet msbuild -h'。”
Tagc

是的,我正在使用它来设置版本,公司名称,产品等...它真的很有用:)
Jay

1

我在.csproj中这样做

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

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


0

将/ p:PropertyName = Value作为参数传递对我不起作用(ASP.Net Core 2.0 Web App)。我在marketpace上找到了清单版本控制构建任务:https ://marketplace.visualstudio.com/items ? itemName = richardfennellBM.BM-VSTS-Versioning-Task


我正在通过.NET Core 2.0应用程序精确使用此功能-并且它对我有用。您能否扩大答案以显示您正在使用的实际MSbuild命令?
杰伊,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.