Jas*_*n H 93 c# visual-studio .net-core visual-studio-2017 .net-standard
我花了几个小时的时间试图找到一种在.NETCoreApp 1.1(Visual Studio 2017)中自动增加版本的方法.
我知道AssemblyInfo.cs是在文件夹中动态创建的: obj/Debug/netcoreapp1.1/
它不接受旧的方法:
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]
如果我将项目设置为包我可以在那里设置版本,但这似乎用于构建AssemblyInfo.cs文件.
我的问题是,有没有人想出如何控制.NET Core(或.NETStandard)项目中的版本.
MiF*_*vil 58
<Deterministic>False</Deterministic>在<PropertyGroup>.csproj 的一部分中添加
MakeVersion*工作的解决方法在".Net Core#22660上的[AssemblyVersion]中为通配符混淆错误消息"中描述
只有在构建不确定时才允许使用通配符,这是.Net Core项目的默认设置.添加
<Deterministic>False</Deterministic>到csproj修复了这个问题.
.Net核心开发人员认为在http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html 和编译器中描述的确定性构建有益的原因应该是确定性的:相同的输入生成相同的输出# 372
但是,如果您使用的是TeamCity,TFS或其他CI/CD工具,最好保持版本号受控制并增加它们并将其作为参数传递给构建(如其他答案中所建议的那样),例如
msbuild /t:build /p:Version=YourVersionNumber /p:AssemblyVersion=YourVersionNumber
Run Code Online (Sandbox Code Playgroud)
NuGet包的包装编号
msbuild /t:pack /p:Version=YourVersionNumber
Run Code Online (Sandbox Code Playgroud)
joe*_*and 55
如果您使用Visual Studio Team Services/TFS或其他一些CI构建过程来内置版本控制,则可以使用msbuild的Condition属性,例如:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.0.1-local</Version>
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
</ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
这将告诉.NET Core编译器使用BUILD_BUILDNUMBER环境变量中的任何内容(如果它存在),或者0.0.1-local如果您在本地计算机上进行构建则回退到.
rav*_*oll 21
我一直在使用csproj配置格式为VS2017中的Net Core应用程序寻找版本增量器.
我找到了一个名为dotnet bump的项目,该项目适用于project.json格式,但很难找到.csproj格式的解决方案.作者dotnet bump实际上提出了.csproj格式的解决方案,它被称为MSBump.
在GitHub上有一个项目:
https://github.com/BalassaMarton/MSBump
在那里你可以看到Nuget上的代码及其可用的代码.只需在Nuget上搜索MSBump.
Hol*_*Jan 13
我提出的解决方案与旧的AssemblyVersion属性几乎相同,只有星号(*) - AssemblyVersion("1.0. ")*
对价值观的AssemblyVersion和的AssemblyFileVersion是MSBuild项目.csproj的文件(而不是在AssemblyInfo.cs中)财产文件版本(生成AssemblyFileVersionAttribute)和的AssemblyVersion(产生AssemblyVersionAttribute).在MSBuild过程中,我们使用自定义MSBuild任务生成版本号,然后使用来自task的新值覆盖这些FileVersion和AssemblyVersion属性的值.
首先,我们创建自定义MSBuild任务GetCurrentBuildVersion:
public class GetCurrentBuildVersion : Task
{
[Output]
public string Version { get; set; }
public string BaseVersion { get; set; }
public override bool Execute()
{
var originalVersion = System.Version.Parse(this.BaseVersion ?? "1.0.0");
this.Version = GetCurrentBuildVersionString(originalVersion);
return true;
}
private static string GetCurrentBuildVersionString(Version baseVersion)
{
DateTime d = DateTime.Now;
return new Version(baseVersion.Major, baseVersion.Minor,
(DateTime.Today - new DateTime(2000, 1, 1)).Days,
((int)new TimeSpan(d.Hour, d.Minute, d.Second).TotalSeconds) / 2).ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
任务类继承自Microsoft.Build.Utilities.Core NuGet包中的Microsoft.Build.Utilities.Task类.它在输入上使用BaseVersion属性(可选)并在Version输出属性中返回生成的版本.获取版本号的逻辑与.NET自动版本控制相同(内部版本号是自2000年1月1日起的天数,而修订版是午夜后的半秒).
要构建此MSBuild任务,我们将.NET Class 1.3类库项目类型与此类一起使用.
.csproj文件可能如下所示:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<AssemblyName>DC.Build.Tasks</AssemblyName>
<RootNamespace>DC.Build.Tasks</RootNamespace>
<PackageId>DC.Build.Tasks</PackageId>
<AssemblyTitle>DC.Build.Tasks</AssemblyTitle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.1012" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.1012" />
</ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
这个任务项目也可以在我的GitHub holajan/DC.Build.Tasks中找到
现在我们设置MSBuild来使用此任务并设置FileVersion和AssemblyVersion属性.在.csproj文件中,它看起来像这样:
<Project Sdk="Microsoft.NET.Sdk">
<UsingTask TaskName="GetCurrentBuildVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\DC.Build.Tasks.dll" />
<PropertyGroup>
...
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
</PropertyGroup>
...
<Target Name="BeforeBuildActionsProject1" BeforeTargets="BeforeBuild">
<GetCurrentBuildVersion BaseVersion="$(FileVersion)">
<Output TaskParameter="Version" PropertyName="FileVersion" />
</GetCurrentBuildVersion>
<PropertyGroup>
<AssemblyVersion>$(FileVersion)</AssemblyVersion>
</PropertyGroup>
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
这里的进口商品:
此解决方案的优点是它不仅可以从构建服务器上构建,还可以在dotnet构建或Visual Studio的手动构建中工作.
Fab*_*doy 11
您可以使用MSBuild属性函数根据当前日期设置版本后缀:
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<VersionSuffix>pre$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmm))</VersionSuffix>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
这将输出一个名为PackageName.1.0.0-pre20180807-1711.nupkg的包.
有关MSBuild属性函数的更多详细信息:https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions
现在,这些值在.csproj文件中设置:
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AssemblyVersion>1.0.6.0</AssemblyVersion>
<FileVersion>1.0.6.0</FileVersion>
<Version>1.0.1</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
如果您进入项目设置的" 包"选项卡,则这些值与您看到的值相同.虽然我认为您不能使用*自动增量版本,但您可以做的是引入一个后处理步骤来替换您的版本(例如,作为持续集成的一部分).
dotnet build /p:AssemblyVersion=1.2.3.4
我回答说:"有没有人想出如何控制.NET Core(或.NETStandard)项目中的版本." 我发现这个问题试图在CI构建的上下文中解决这个问题.我想将程序集版本设置为CI内部版本号.
您可以在 csproj 文件中执行如下操作。我没搞清楚数学。我在 Stack Overflow 上的其他地方发现了它,但这可以工作,并且会为您提供类似于 1.0.* 的版本。
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<FileVersion>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays).$([System.Math]::Floor($([MSBuild]::Divide($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds), 1.32))))</FileVersion>
<Version>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays)</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
综上所述:您可以AssemblyInfo.cs通过以下方式恢复旧行为:
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
Run Code Online (Sandbox Code Playgroud)
但不建议使用这种方法,因为关闭GenerateAssemblyInfo可能会导致基础设施问题,例如。更具选择性的方法:
<Deterministic>false</Deterministic>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<AssemblyVersion>1.2.*</AssemblyVersion>
Run Code Online (Sandbox Code Playgroud)
你不需要AssemblyInfo.cs更多了。
我接受了上面的答案,因为@Gigi是正确的(截至目前),但我很恼火,并提出了以下PowerShell脚本.
首先,我在我的解决方案文件夹(UpdateBuildVersion.ps1)中有脚本:
#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"
#Read csproj (XML)
$xml = [xml](Get-Content $path)
#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion
#Split the Version Numbers
$avMajor, $avMinor, $avBuild = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")
#Increment Revision
$avBuild = [Convert]::ToInt32($avBuild,10)+1
$fvBuild = [Convert]::ToInt32($fvBuild,10)+1
#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"
#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)
我把它添加到csproj文件中:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyVersion>0.0.1</AssemblyVersion>
<FileVersion>0.0.1</FileVersion>
<PreBuildEvent>powershell.exe –NonInteractive –ExecutionPolicy Unrestricted -command "& {$(SolutionDir)UpdateBuildVersion.ps1}"</PreBuildEvent>
</PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
即使将其设置为PreBuildEvent,事实上版本号在文件加载到内存之后才会更新,因此版本号在下一次构建之前不会反映出来.实际上,您可以将其更改为PostBuildEvent,它将具有相同的效果.
我还创建了以下两个脚本:(UpdateMinorVersion.ps1)
#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"
#Read csproj (XML)
$xml = [xml](Get-Content $path)
#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion
#Split the Version Numbers
$avMajor, $avMinor, $avBuild = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")
#Increment Minor Version - Will reset all sub nodes
$avMinor = [Convert]::ToInt32($avMinor,10)+1
$fvMinor = [Convert]::ToInt32($fvMinor,10)+1
$avBuild = 0
$fvBuild = 0
#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"
#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)
(UpdateMajorVersion.ps1)
#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"
#Read csproj (XML)
$xml = [xml](Get-Content $path)
#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion
#Split the Version Numbers
$avMajor, $avMinor, $avBuild = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")
#Increment Major Version - Will reset all sub nodes
$avMajor = [Convert]::ToInt32($avMajor,10)+1
$fvMajor = [Convert]::ToInt32($fvMajor,10)+1
$avMinor = 0
$fvMinor = 0
$avBuild = 0
$fvBuild = 0
#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"
#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)
感谢@joelsand 为我指明了正确的方向。
当 DevOps Build 运行时,我不得不稍微改变他的答案,我得到以下异常
指定的版本字符串不符合推荐格式-major.minor.build.revision
我不得不在major.minor.build 部分的末尾添加$(BUILD_BUILDNUMBER)。为了对实际版本进行重复数据删除,我还使用了版本前缀:
<PropertyGroup>
<VersionPrefix>1.0.3</VersionPrefix>
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
对我有用的是使用 定义 Patch 和 Revision PropertyGroup,然后您可以使用此变量作为版本(如果需要,还可以使用前缀)。版本号必须是短数字,因此我使用 YearMonth 表示补丁,使用 MinutesOfDay 表示修订。将此行添加到您的 csproj 文件中:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VersionMajor>0</VersionMajor>
<VersionMinor>9</VersionMinor>
<VersionPatch Condition="'$(VersionPatch)' == ''">$([System.DateTime]::UtcNow.ToString("yyMM"))</VersionPatch>
<VersionRevision Condition="'$(VersionRevision)' == ''">$([System.DateTime]::UtcNow.TimeOfDay.TotalMinutes.ToString("0"))</VersionRevision>
</PropertyGroup>
<PropertyGroup>
<OutputType>...</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Title>Software Title</Title>
<Description>...</Description>
<Authors>...</Authors>
<Version>$(VersionMajor).$(VersionMinor).$(VersionPatch).$(VersionRevision)</Version>
</PropertyGroup>
....
</Project>
Run Code Online (Sandbox Code Playgroud)
它可以利用文件以通用方式实现Directory.build.props。更多信息请参见:https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build? view=vs-2019
只需在项目文件夹中添加一个具有此名称的文件并将这些行放在那里即可。
我在这里寻找共享项目的解决方案。就我而言,我解决了这个问题,Version.build.props在我的共享项目中添加了一个具有上面所示结构的文件,并且在使用我的共享代码的项目的任何 csproj 文件中只添加了一个新行:
<!-- Shared project import -->
<Import Project="..\Shared\Shared.projitems" Label="Shared" />
<!-- Version number generator -->
<Import Project="$([MSBuild]::GetPathOfFileAbove('Version.Build.props', '$(MSBuildThisFileDirectory)../Shared/'))" />
Run Code Online (Sandbox Code Playgroud)
我会将这段代码留在这里,以防万一有人需要它。
*解决方案针对 .Net5 进行了测试,但应该适用于早期版本。
使用 GIT 的标签/描述功能,根据您的 GIT 设置启用 .NET Core / .NET 无论项目的版本控制。
我一直在使用 Prebuild.targets.xml 文件,该文件位于项目的根文件夹中,并包含在 csproj 文件中,如下所示:
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="PreBuild.targets.xml" />
...
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
Run Code Online (Sandbox Code Playgroud)
使用“GenerateAssembyInfo”标签禁用自动程序集信息生成。
然后 Prebuild.targets.xml 将生成一个 CommonAssemblyInfo.cs 文件,您可以在其中根据您的 GIT 版本包含所需的版本标签
注意:我在其他地方找到了 Prebuilds.targets.xml,所以没有费心清理它。)
Prebuild.targets.xml 文件:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask
TaskName="GetVersion"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
<ParameterGroup>
<VersionString ParameterType="System.String" Required="true" />
<Version ParameterType="System.String" Output="true" />
<Commit ParameterType="System.String" Output="true" />
<VersionSuffix ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<!--<Reference Include="" />-->
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var match = Regex.Match(VersionString, @"^(?<major>\d+)\.(?<minor>\d+)(\.?(?<patch>\d+))?-(?<revision>\d+)-(?<commit>[a-z0-9-]+)$");
int major, minor, patch, revision;
Int32.TryParse(match.Groups["major"].Value, out major);
Int32.TryParse(match.Groups["minor"].Value, out minor);
Int32.TryParse(match.Groups["patch"].Value, out patch);
Int32.TryParse(match.Groups["revision"].Value, out revision);
_Version = new Version(major, minor, patch, revision).ToString();
_Commit = match.Groups["commit"].Value;
]]>
</Code>
</Task>
</UsingTask>
<UsingTask
TaskName="GitExistsInPath"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
<ParameterGroup>
<Exists ParameterType="System.Boolean" Output="true" />
</ParameterGroup>
<Task>
<!--<Reference Include="" />-->
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var values = Environment.GetEnvironmentVariable("PATH");
foreach (var path in values.Split(';')) {
var exeFullPath = Path.Combine(path, "git.exe");
if (File.Exists(exeFullPath)) {
Exists = true;
return true;
}
var cmdFullPath = Path.Combine(path, "git.cmd");
if (File.Exists(cmdFullPath)) {
Exists = true;
return true;
}
}
Exists = false;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="CreateCommonVersionInfo" BeforeTargets="CoreCompile">
<Message Importance="high" Text="CreateCommonVersionInfo" />
<GitExistsInPath>
<Output TaskParameter="Exists" PropertyName="GitExists"/>
</GitExistsInPath>
<Message Importance="High" Text="git not found!" Condition="!$(GitExists)"/>
<Exec Command="git describe --tags --long --dirty > $(ProjectDir)version.txt" Outputs="$(ProjectDir)version.txt" WorkingDirectory="$(SolutionDir)" IgnoreExitCode="true" Condition="$(GitExists)">
<Output TaskParameter="ExitCode" PropertyName="ExitCode" />
</Exec>
<Message Importance="high" Text="Calling git failed with exit code $(ExitCode)" Condition="$(GitExists) And '$(ExitCode)'!='0'" />
<ReadLinesFromFile File="$(ProjectDir)version.txt" Condition="$(GitExists) And '$(ExitCode)'=='0'">
<Output TaskParameter="Lines" ItemName="OutputLines"/>
</ReadLinesFromFile>
<Message Importance="High" Text="Tags: @(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'"/>
<Delete Condition="Exists('$(ProjectDir)version.txt')" Files="$(ProjectDir)version.txt"/>
<GetVersion VersionString="@(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'">
<Output TaskParameter="Version" PropertyName="VersionString"/>
<Output TaskParameter="Commit" PropertyName="Commit"/>
</GetVersion>
<PropertyGroup>
<VersionString Condition="'$(VersionString)'==''">0.0.0.0</VersionString>
</PropertyGroup>
<Message Importance="High" Text="Creating CommonVersionInfo.cs with version $(VersionString) $(Commit)" />
<WriteLinesToFile Overwrite="true" File="$(ProjectDir)CommonAssemblyInfo.cs" Encoding="UTF-8" Lines='using System.Reflection%3B
// full version: $(VersionString)-$(Commit)
[assembly: AssemblyVersion("$(VersionString)")]
[assembly: AssemblyInformationalVersion("$(VersionString)")]
[assembly: AssemblyFileVersion("$(VersionString)")]' />
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
编辑:如果您正在使用 MSBUILD 进行构建
$(SolutionDir)
Run Code Online (Sandbox Code Playgroud)
可能会给您带来麻烦,请使用
$(ProjectDir)
Run Code Online (Sandbox Code Playgroud)
反而
<PropertyGroup>
<SecondsSinceEpoch>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::MinValue)).TotalSeconds)</SecondsSinceEpoch>
<Revision>$([System.Math]::Truncate($([System.Decimal]::Remainder($(SecondsSinceEpoch), 100000))))</Revision>
<Version>1.7.0.$(Revision)</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
我对通过设置一个体面的价值的看法.csproj。不幸的是,如果您的下一次重建是在几100000秒钟之后,那么它将是相同的值。不过,比MSBump更好的是让每次构建都重新构建。
如果构建缓慢或自动化,可以使用TotalMinutes、TotalDays等。
| 归档时间: |
|
| 查看次数: |
56034 次 |
| 最近记录: |