การกำหนดเวอร์ชันอัตโนมัติใน Visual Studio 2017 (.NET Core)


112

ฉันใช้เวลาสองสามชั่วโมงในการหาวิธีเพิ่มเวอร์ชันที่เพิ่มขึ้นอัตโนมัติใน. NETCoreApp 1.1 (Visual Studio 2017)

ฉันรู้ว่ากำลังสร้าง AssemblyInfo.cs แบบไดนามิกในโฟลเดอร์: obj/Debug/netcoreapp1.1/

ไม่ยอมรับวิธีการเดิมของ: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

ถ้าฉันตั้งค่าโปรเจ็กต์เป็นแพ็กเกจฉันสามารถตั้งค่าเวอร์ชันได้ แต่ดูเหมือนว่าจะใช้ในการสร้างไฟล์ AssemblyInfo.cs

คำถามของฉันคือมีใครคิดบ้างว่าจะควบคุมเวอร์ชันในโครงการ. NET Core (หรือ. NETStandard สำหรับเรื่องนั้น) ได้อย่างไร


ฉันไม่รู้ว่าคุณไปได้ไกลแค่ไหน แต่ดูเหมือนว่าฉันถามคำถามเดียวกันเกือบคนละแบบ ( stackoverflow.com/a/43280282/685341 ) - บางทีคำตอบที่ยอมรับสำหรับคำถามนี้จะช่วยคุณได้ คุณสามารถส่ง/p:แฟล็กไปdotnet msbuildในบิลด์สคริปต์ของคุณและกำหนดเวอร์ชัน บริษัท ลิขสิทธิ์ ... สิ่งดีๆทั้งหมดนั้น
เจ

2
ขอบคุณสำหรับข้อมูล. เพียงแค่เปิดตัวเลือกเพิ่มเติม
Jason H

ก่อนหน้านี้ * ได้รับการสนับสนุนสำหรับ AssemblyVersion ไม่ใช่สำหรับ AssemblyFileVersion โปรดดูที่ฉันสามารถเพิ่มเวอร์ชันการสร้างไฟล์โดยอัตโนมัติเมื่อใช้ Visual Studio ได้หรือไม่
Michael Freidgeim

4
FWIW สัญลักษณ์แทนในเวอร์ชันแอสเซมบลีไม่ได้รับการสนับสนุนเนื่องจากสำหรับโปรเจ็กต์ใหม่เหล่านี้โหมด "กำหนด" ของคอมไพเลอร์จะแอ็คทีฟโดยค่าเริ่มต้น เนื่องจากการเพิ่มขึ้นอัตโนมัติจะทำลายดีเทอร์มินิซึม (อินพุตเดียวกัน> เอาต์พุตเดียวกัน) จึงไม่ได้รับอนุญาตในโหมดนั้น คุณสามารถตั้งค่า<Deterministic>False</Deterministic>ใน csproj เพื่อใช้งานได้ (หรือใช้ตรรกะ MSbuild อื่น ๆ เพื่อคำนวณ<VersionPrefix>/ <Version>)
Martin Ullrich

คำตอบ:


23

ฉันกำลังมองหาตัวเพิ่มเวอร์ชันสำหรับแอป Net Core ใน VS2017 โดยใช้รูปแบบการกำหนดค่า csproj

ฉันพบโปรเจ็กต์ชื่อ dotnet bump ที่ใช้ได้กับรูปแบบ project.json แต่พยายามหาวิธีแก้ปัญหาสำหรับรูปแบบ. csproj ผู้เขียน dotnet Bump ได้คิดค้นวิธีแก้ปัญหาสำหรับรูปแบบ. csproj และเรียกว่า MSBump

มีโครงการเกี่ยวกับ GitHub อยู่ที่:

https://github.com/BalassaMarton/MSBump

ซึ่งคุณสามารถดูรหัสและรหัสที่มีอยู่ใน Nuget ได้เช่นกัน เพียงค้นหา MSBump ใน Nuget


1
ฉันขอแนะนำให้ใช้ MSBump เวอร์ชัน 2.1.0 ล่าสุดซึ่งรองรับการกำหนดค่าการสลับได้ดีขึ้นและยังตั้งค่าเวอร์ชันสำหรับบิลด์ปัจจุบันไม่ใช่เวอร์ชันถัดไป (เช่นเวอร์ชันก่อนหน้า)
Márton Balassa

ฉันเห็นว่าตอนนี้ยังรองรับ MSBuild ในขณะที่ก่อนหน้านี้ต้องใช้ Visual Studio
ravetroll

2
ใช่และยังรองรับโครงการหลายเป้าหมาย
Márton Balassa

4
ลองใช้ GitVersioning อาจเหมาะที่จะทำงานบนสภาพแวดล้อม CI ของคุณ github.com/AArnott/Nerdbank.GitVersioning
Henrique

1
MSBump เวอร์ชันที่เพิ่มขึ้นในทุกๆบิลด์แม้ว่าคุณจะไม่ได้เปลี่ยนแปลงอะไรก็ตาม แต่ก็ทำให้เกิดปัญหามากมายในระยะยาว และบางครั้งเวอร์ชันไม่ตรงกันและเวอร์ชันหนึ่งอยู่หลังเวอร์ชันอื่น
Konrad

68

เพิ่ม <Deterministic>False</Deterministic>ใน<PropertyGroup>ส่วนของ. csproj

วิธีแก้ปัญหาเพื่อให้ AssemblyVersion * ทำงานได้อธิบายไว้ใน“ ข้อความแสดงข้อผิดพลาดที่สับสนสำหรับสัญลักษณ์แทนใน [AssemblyVersion] บน. Net Core # 22660”

อนุญาตให้ใช้สัญลักษณ์แทนหากบิลด์ไม่ได้ถูกกำหนดซึ่งเป็นค่าเริ่มต้นสำหรับโปรเจ็กต์. Net Core การเพิ่ม  <Deterministic>False</Deterministic> ใน csproj ช่วยแก้ปัญหาได้

เหตุผลที่นักพัฒนา. Net Core พิจารณาว่าการสร้างแบบกำหนดเป็นประโยชน์ที่อธิบายไว้ใน 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

หมายเลขแพ็คเกจสำหรับแพ็คเกจ NuGet

msbuild /t:pack /p:Version=YourVersionNumber   

ขอบคุณ! ฉันรู้ว่ามีคันโยกที่ซ่อนอยู่สำหรับเปิดห้องสมบัติ! ฉันกำลังย้ายโครงการเก่าไปยัง. NET SDK ใหม่และฉันต้องการดำเนินการอย่างรวดเร็วโดยไม่ต้องยุ่งยากในการค้นหาโซลูชันการเพิ่มเวอร์ชันอัตโนมัติ ในความเป็นจริงยิ่งเข้ากันได้กับวิธีเก่า ๆ มากเท่าไหร่ก็ยิ่งดีสำหรับกรณีของฉัน
Ivaylo Slavov

นี่คือคำตอบที่ดีที่สุด IMO ช่วยให้เครื่องมือสร้างทำงานได้อย่างถูกต้อง อย่างน้อยฉันก็สามารถใช้กลไกภายนอกเพื่อป้อนหมายเลขลงในบิลด์ได้ทันที
Michael Yanni

โปรดขยายคำตอบของคุณให้มากขึ้น: ส่วนเพิ่มเติมที่แนะนำจะต้องเข้าไปในส่วน <PropertyGroup> ของ. csproj และขอบคุณสำหรับคำตอบที่ยอดเยี่ยมนี้แน่นอน!
GerardV

1
@gerardv เสร็จแล้ว แต่คุณสามารถปรับปรุงแก้ไขได้ด้วยตัวเองstackoverflow.com/help/editing
Michael Freidgeim

62

ถ้าคุณกำลังใช้ Visual Studio Team Services / TFS หรือกระบวนการสร้าง CI อื่น ๆ เพื่อให้มีการกำหนดเวอร์ชันในตัวคุณสามารถใช้Conditionแอตทริบิวต์ของ msbuild ได้เช่น:

<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>

สิ่งนี้จะบอกคอมไพลเลอร์. NET Core ให้ใช้สิ่งที่อยู่ในBUILD_BUILDNUMBERตัวแปรสภาพแวดล้อมหากมีอยู่หรือทางเลือก0.0.1-localหากคุณกำลังสร้างบนเครื่องในระบบของคุณ


ดีฉันชอบแนวทางนี้เพราะตัวแปรสภาพแวดล้อมสามารถตั้งค่าได้ที่เซิร์ฟเวอร์การสร้างในขณะที่เงื่อนไขเหล่านี้ขัดขวางการประกอบชุดในไบนารี
jbooker

ดูเหมือนจะไม่ทำงานใน TFS 2010 แต่หวังว่าเราจะย้ายออกไปเร็ว ๆ นี้!
Mark Adamson

ไม่ใช่วิธีการแก้ปัญหาที่ไม่ดี แต่อาจใช้งานได้เล็กน้อยหากโซลูชันมีโครงการจำนวนมาก
tofutim

ทางออกที่ดี. ฉันได้รับข้อยกเว้น Build แม้ว่า ฉันต้องเปลี่ยน config เล็กน้อยเพื่อแก้ไข stackoverflow.com/a/59858009/106227
Stu Harper

ใช้งานได้ดีกับ. NET Core 2.1.2 และ TFS2017U3
Dave Johnson

16

ฉันคิดวิธีแก้ปัญหาที่เกือบจะเหมือนกับแอตทริบิวต์AssemblyVersionเก่าที่มี star (*) - AssemblyVersion ("1.0. ") *

ค่าสำหรับAssemblyVersionและAssemblyFileVersionอยู่ในไฟล์MSBuild project .csproj (ไม่อยู่ในAssemblyInfo.cs ) เป็นคุณสมบัติFileVersion (สร้างAssemblyFileVersionAttribute ) และAssemblyVersion (สร้างAssemblyVersionAttribute ) ในกระบวนการ MSBuild เราใช้งาน MSBuild ที่กำหนดเองของเราเพื่อสร้างหมายเลขเวอร์ชันจากนั้นเราจะแทนที่ค่าของคุณสมบัติ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();
    }
}

คลาสงานสืบทอดจากMicrosoft.Build.Utilities.Taskจากแพ็คเกจMicrosoft.Build.Utilities.Core NuGet ใช้คุณสมบัติ BaseVersion (ทางเลือก) บนอินพุตและส่งคืนเวอร์ชันที่สร้างขึ้นในคุณสมบัติเอาต์พุตเวอร์ชัน ตรรกะในการรับหมายเลขเวอร์ชันจะเหมือนกับการกำหนดเวอร์ชันอัตโนมัติ. NET (หมายเลขบิลด์คือจำนวนวันนับตั้งแต่ 1/1/2000 และการแก้ไขคือครึ่งวินาทีนับตั้งแต่เที่ยงคืน)

ในการสร้างงาน MSBuild นี้เราใช้ประเภทโครงการไลบรารีคลาส. NET Standard 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>

โครงการงานนี้ยังมีอยู่ใน 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>

สิ่งสำคัญที่นี่:

  • กล่าวถึงอังกษงานนำเข้าจาก GetCurrentBuildVersion DC.Build.Tasks.dll ถือว่าไฟล์ dll นี้อยู่ในไดเร็กทอรีหลักจากไฟล์. csproj ของคุณ
  • BeforeBuildActionsProject1 Target ของเราที่เรียกใช้งานต้องมีชื่อที่ไม่ซ้ำกันต่อโปรเจ็กต์ในกรณีที่เรามีโปรเจ็กต์เพิ่มเติมในโซลูชันที่เรียกว่างาน GetCurrentBuildVersion

ข้อดีของโซลูชันนี้คือไม่เพียง แต่ใช้งานได้จากการสร้างบนเซิร์ฟเวอร์ที่สร้างขึ้นเท่านั้น แต่ยังรวมถึงการสร้างด้วยตนเองจากdotnet buildหรือ Visual Studio ด้วย


4
ฉันขอแนะนำให้ใช้DateTime.UtcNowแทนDateTime.NowวิธีการGetCurrentBuildVersionString()โดยเฉพาะอย่างยิ่งถ้ารหัสถูกเรียกใช้บนเครื่องสร้างอัตโนมัติ อาจทำงานตอนตี 2 หรือ 3 น. ในตอนเช้าเมื่อคอมพิวเตอร์ของคุณเปลี่ยนเป็น / จากเวลาออมแสง ด้วยDateTime.Nowในสถานการณ์ที่คุณอาจจะไปข้างหลังในแง่ของรุ่น เป็นที่ยอมรับว่านี่เป็นกรณีมุมและฉันก็ยอมรับว่าฉันจู้จี้จุกจิก :-) นอกจากนี้ปัญหาจะหายไปหากคุณกำหนดเขตเวลาเดียวกันในเครื่องสร้างทั้งหมดและไม่ปรับเป็นเวลาออมแสง
Manfred

มีแพ็คเกจ NuGet สำหรับสิ่งนี้หรือยัง?
Jonathan Allen

@ โจนาธานอัลเลนไม่ฉันไม่มีแผนสำหรับแพ็คเกจนักเก็ตเนื่องจากชื่อต่างกันในแต่ละโครงการ คุณสามารถดาวน์โหลดงาน build ที่คอมไพล์แล้วได้ในgithub.com/holajan/DC.Build.Tasks/tree/master/dist folder
HolaJan

เราใช้แอปคอนโซลที่กำหนดเองเพื่อดึงเวอร์ชันของเราจากเซิร์ฟเวอร์และสร้างไฟล์ AssemblyInfo.cs ก่อนสร้าง แนวทางนี้เหมาะสำหรับสิ่งที่เราทำ คุณสามารถใช้วิธีนี้เพื่อพุชเวอร์ชันใน "เวอร์ชัน" ของคุณลักษณะแพ็คของโครงการใหม่ได้หรือไม่? คงจะดี แต่ฉันเดาว่าเราสามารถกลับไปใช้ nuget.exe เพื่อทำแพ็กเกจได้เช่นกันเพราะเราจำเป็นต้องเผยแพร่ด้วย
David Ritchie

15

คุณสามารถใช้ฟังก์ชันคุณสมบัติ MSBuild เพื่อตั้งค่าส่วนต่อท้ายเวอร์ชันตามวันที่ปัจจุบัน:

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
  <VersionSuffix>pre$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmm))</VersionSuffix>
</PropertyGroup>

นี้ออกจะเป็นแพคเกจที่มีชื่อเหมือน: PackageName.1.0.0-pre20180807-1711.nupkg

รายละเอียดเพิ่มเติมเกี่ยวกับฟังก์ชันคุณสมบัติ MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

Versionจะเกิดขึ้นจากการรวมกันของVersionPrefixและVersionSuffixหรือถ้าVersionSuffixว่างเปล่าVersionPrefixเท่านั้น

<PropertyGroup>
  <VersionPrefix>1.0.0</VersionPrefix>
</PropertyGroup>

สิ่งนี้มีประโยชน์จริงๆ
เจอร์รีนิกสัน

12

ฉันยอมรับคำตอบข้างต้นเพราะ @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)

ฉันเพิ่มสิ่งนี้ลงในไฟล์ 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>

แม้ว่าจะผ่านการตั้งค่าให้เป็น 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)

(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)

10

dotnet build /p:AssemblyVersion=1.2.3.4

ฉันตอบสนองต่อ: "มีใครรู้วิธีควบคุมเวอร์ชันในโครงการ. NET Core (หรือ. NETStandard สำหรับเรื่องนั้น) บ้าง" ฉันพบว่าคำถามนี้พยายามแก้ปัญหานี้ในบริบทของการสร้าง CI ฉันต้องการตั้งค่าเวอร์ชันแอสเซมบลีเป็นหมายเลขบิลด์ CI


1
ชื่อเรื่องระบุว่า "Auto Versioning in Visual Studio 2017 (.NET Core)" การสร้างด้วยตนเองสอดคล้องกับ "Visual Studio 2017" ที่ใดกันแน่
JCKödel

4
ฉันตอบสนองต่อ: "มีใครรู้วิธีควบคุมเวอร์ชันในโครงการ. NET Core (หรือ. NETStandard สำหรับเรื่องนั้น) บ้าง" ฉันพบว่าคำถามนี้พยายามแก้ปัญหานี้ในบริบทของการสร้าง CI ฉันต้องการตั้งค่าเวอร์ชันแอสเซมบลีเป็นหมายเลขบิลด์ CI ขออภัยหากคุณรู้สึกว่าสิ่งนี้ไม่เกี่ยวข้องกับคำถามในมือ
Chris McKenzie

มันเป็นส่วนประกอบที่มีประโยชน์สำหรับฉันขอบคุณ ฉันจะใช้สิ่งนี้เป็นส่วนหนึ่งของโซลูชัน CI
Mark Adamson

1
@ChrisMcKenzie: ความคิดเห็นของคุณควรรวมอยู่ในคำตอบเพื่อให้เจตนาของคุณชัดเจน
Michael Freidgeim

** สิ่งนี้ใช้ไม่ได้สำหรับฉันในโปรเจ็กต์มาตรฐานเมื่อไม่ได้ระบุ assemblyinfo.cs และเวอร์ชันอยู่ใน csproj ...
tofutim

9

ตอนนี้ค่าเหล่านี้ถูกตั้งค่าใน.csprojไฟล์:

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <AssemblyVersion>1.0.6.0</AssemblyVersion>
    <FileVersion>1.0.6.0</FileVersion>
    <Version>1.0.1</Version>
</PropertyGroup>

ค่าเหล่านี้เป็นค่าเดียวกับที่คุณเห็นหากคุณอยู่ในแท็บแพ็คเกจในการตั้งค่าโครงการ แม้ว่าฉันไม่คิดว่าคุณจะสามารถใช้*เพื่อเพิ่มเวอร์ชันอัตโนมัติได้ แต่สิ่งที่คุณทำได้คือแนะนำขั้นตอนหลังการประมวลผลที่แทนที่เวอร์ชันให้คุณ (เช่นเป็นส่วนหนึ่งของการผสานรวมอย่างต่อเนื่องของคุณ)


6
ฉันกลัวว่านี่จะเป็นคำตอบ ฉันจะดูว่าฉันสามารถทำขั้นตอนก่อนสร้างเพื่อเพิ่มได้หรือไม่
Jason H

3
ตามที่ระบุไว้ในเธรดอื่นรูปแบบ csproj ใหม่ช่วยให้คุณสามารถปิดการสร้างไฟล์ assemblyinfo โดยอัตโนมัติและให้คุณระบุไฟล์ของคุณเอง ฉันทำตามคำแนะนำของคำตอบของ natemcmaster ที่นี่และใช้ไฟล์ AssemblyInfo.cs มาตรฐาน: stackoverflow.com/questions/42138418/…
James Eby

5
เหตุใดพวกเขาจึงลบการเพิ่มอัตโนมัติ มันใช้งานได้ดีและเรียบง่ายมากสำหรับฉันเป็นเวลาหลายปี ฉันพุช master, CI builds และ Increments จากนั้นเวอร์ชันจะถูกอ่านโดยตรงจาก DLL ที่สร้างขึ้นโดยใช้สคริปต์ PS จากนั้นใช้เวอร์ชันนั้นเป็นอาร์กิวเมนต์เมื่อกดไปที่ NuGet ง่ายมาก ตอนนี้แตกแล้ว.
Luke Puplett

1
@LukePuplett เหมือนกันที่นี่ น่าหงุดหงิดจัง!
Shimmy Weitzhandler

@LukePuplett: ดู [“ ข้อความแสดงข้อผิดพลาดที่สับสนสำหรับสัญลักษณ์แทนใน AssemblyVersion บน. Net Core # 22660”] ( github.com/dotnet/roslyn/issues/22660 ) เหตุผลที่พวกเขาพิจารณาว่าการสร้างแบบกำหนดเป็นประโยชน์ที่อธิบายไว้ในblog.paranoidcoding.com /
2016/04/05

5

ฉันทำเครื่องมือ CLI ง่ายสำหรับการตั้งค่า .csproj .NET แกนสตริงรุ่นที่นี่ คุณสามารถรวมเข้ากับเครื่องมือเช่น GitVersion สำหรับการชนเวอร์ชันอัตโนมัติระหว่างการสร้าง CI หากนั่นคือสิ่งที่คุณต้องการ


@JasonH ขอบคุณโปรดแจ้งให้เราทราบหากคุณมีปัญหาใด ๆ
Tagc

อัจฉริยะที่น่ารังเกียจ รักเลย!
pms1969

4

หากต้องการเปิดใช้งานการกำหนดเวอร์ชันของโครงการ. Net Core / .Net Whatever ของคุณตามการตั้งค่า GIT ของคุณโดยใช้แท็ก / อธิบายฟังก์ชันการทำงานของ GIT

ฉันใช้ไฟล์ Prebuild.targets.xml ซึ่งอยู่ในโฟลเดอร์รูทของโปรเจ็กต์และรวมอยู่ในไฟล์ csproj เช่น:

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="PreBuild.targets.xml" />
  ...
  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>

ใช้แท็ก "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>

แก้ไข: หากคุณกำลังสร้างโดยใช้ MSBUILD ไฟล์

 $(SolutionDir)

อาจทำให้คุณเดือดร้อนใช้

 $(ProjectDir)

แทน


ดี! VersionSuffix สิ้นสุดการตั้งค่าหรือใช้งานหรือไม่ ดูเหมือนจะไม่ใช่
Mark Adamson

4

คุณสามารถทำสิ่งต่อไปนี้ภายในไฟล์ csproj ฉันคิดเลขไม่ออก ฉันพบว่าที่อื่นใน stackoverflow แต่วิธีนี้ใช้งานได้และจะให้บางสิ่งที่คล้ายกับ 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>

3

ตอนนี้ส่วนขยาย Automatic Versions สำหรับ Visual Studio รองรับ. Net Core และ. Net Standard autoincrementing ในอินเทอร์เฟซผู้ใช้ที่เรียบง่าย

https://marketplace.visualstudio.com/items?itemName=PrecisionInfinity.AutomaticVersions


1
ฉันได้ทำการทดสอบอย่างรวดเร็วด้วยโซลูชันการสาธิต (แอป windows) และใช้งานได้กับโครงการมาตรฐาน. net เป็นการทดสอบที่รวดเร็วดังนั้นต้องเจาะลึกลงไปเพื่อตรวจสอบว่าทำตามที่เราต้องการหรือไม่ แต่คุณแน่ใจว่าสามารถลองอันนี้
ArieKanarie

3

ขอบคุณ @joelsand ที่ชี้ให้ฉันไปในทิศทางที่ถูกต้อง

ฉันต้องเปลี่ยนคำตอบเล็กน้อยเมื่อ DevOps Build ทำงานฉันได้รับข้อยกเว้นดังต่อไปนี้

The specified version string does not conform to the recommended format - major.minor.build.revision

ฉันต้องเพิ่ม $ (BUILD_BUILDNUMBER) ที่ส่วนท้ายของส่วน major.minor.build หากต้องการยกเลิกการทำซ้ำเวอร์ชันจริงฉันยังใช้คำนำหน้าเวอร์ชัน:

<PropertyGroup>
    <VersionPrefix>1.0.3</VersionPrefix>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>

ฉันมีปัญหาเดียวกันและคำตอบของคุณได้รับการแก้ไขแล้ว ขอบคุณ.
ผู้เข้าร่วมประชุม

2

เราสามารถใช้พารามิเตอร์พิเศษสำหรับ dotnet publish -- version-suffix 1.2.3

สำหรับเวอร์ชันไฟล์:

<AssemblyVersion Condition=" '$(VersionSuffix)' == '' ">0.0.1.0</AssemblyVersion>
<AssemblyVersion Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</AssemblyVersion>

สำหรับเวอร์ชัน:

<Version Condition=" '$(VersionSuffix)' == '' ">0.0.1</Version>
<Version Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</Version>

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21

--version-suffix <VERSION_SUFFIX>     Defines the value for the $(VersionSuffix) property in the project.

1

ฉันคิดว่าคำตอบนี้จาก @joelsand เป็นคำตอบที่ถูกต้องสำหรับการตั้งค่าหมายเลขเวอร์ชันสำหรับ dotnet core ที่ทำงานบน VSTS

หากต้องการข้อมูลเพิ่มเติมสำหรับคำตอบนี้

BUILD_BUILDNUMBERเป็นจริงเป็นตัวแปรที่กำหนดไว้ล่วงหน้า

ปรากฎว่ามีตัวแปรที่กำหนดไว้ล่วงหน้า 2 เวอร์ชัน

หนึ่งคือ build.xxxx อีกอันคือ BUILD_XXXX

คุณสามารถใช้ได้เฉพาะEnvironment Variable Nameใน cproj


ไม่ได้build.xxxxใช้ในส่วนหน้าสำหรับการอ้างอิงภายในไปป์ไลน์และBUILD_XXXXเป็นค่าเดียวกัน แต่จำเป็นต้องมีการปรับเปลี่ยนไวยากรณ์เล็กน้อยสำหรับการอ้างอิงตัวแปรใน PS หรือไม่
dst3p

1

คุณสามารถลองใช้ตัวเลขหลักคงที่โดยใช้คำต่อท้ายตามวันที่ปัจจุบัน:

  <PropertyGroup>
    <VersionPrefix>1</VersionPrefix>
    <VersionSuffix>$([System.DateTime]::UtcNow.ToString(yyMM)).$([System.DateTime]::UtcNow.ToString(ddHH)).$([System.DateTime]::UtcNow.ToString(mmss))</VersionSuffix>
    <Version Condition=" '$(VersionSuffix)' == '' ">$(VersionPrefix).0.0.1</Version>
    <Version Condition=" '$(VersionSuffix)' != '' ">$(VersionPrefix).$(VersionSuffix)</Version>
  </PropertyGroup>

คุณมีทางออกที่ดีที่นี่ ไม่ใช่ทุกคนที่ชอบใช้ 'DateTime' ในเวอร์ชันของตน
Jason H
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.