Автоматически обновить номер версии

Я бы хотел, чтобы свойство версии моего приложения увеличивалось для каждой сборки, но я не уверен, как включить эту функцию в Visual Studio (2005/2008). Я попытался указать AssemblyVersion как 1.0. *, Но мне не удалось получить именно то, что я хочу.

Я также использую файл настроек, и в более ранних попытках, когда версия сборки меняла, мои настройки сбрасывались до значений по умолчанию, поскольку приложение искало файл настроек в другом каталоге.

Я хотел бы иметь возможность отображать номер версии в виде 1.1.38, чтобы, когда пользователь обнаружил проблему, я мог зарегистрировать версию, которую он использует, а также сказать им обновить, если у них есть старая версия.

Также приветствуется краткое объяснение того, как работает управление версиями. Когда увеличивается номер сборки и версии?

Ответов (8)

Решение

С «встроенным» материалом вы не можете, поскольку использование 1.0. * Или 1.0.0. * Заменит номера ревизии и сборки на закодированную дату / время, что обычно также является хорошим способом.

Дополнительные сведения см. В документации компоновщика сборок в теге / v.

Что касается автоматического увеличения чисел, используйте задачу AssemblyInfo:

AssemblyInfo Задача

Это можно настроить для автоматического увеличения номера сборки.

Есть 2 ошибки:

  1. Каждое из 4 чисел в строке версии ограничено 65535. Это ограничение Windows и вряд ли будет исправлено.
  2. Использование with с Subversion требует небольших изменений:

Тогда получить номер версии довольно просто:

Version v = Assembly.GetExecutingAssembly().GetName().Version;
string About = string.Format(CultureInfo.InvariantCulture, @"YourApp Version {0}.{1}.{2} (r{3})", v.Major, v.Minor, v.Build, v.Revision);

И, чтобы уточнить: в .net или, по крайней мере, в C#, сборка - это на самом деле ТРЕТИЙ номер, а не четвертый, как могли ожидать некоторые люди (например, разработчики Delphi, которые привыкли к Major.Minor.Release.Build).

В .net это Major.Minor.Build.Revision.

Я обнаружил, что достаточно просто отобразить дату последней сборки, используя следующее везде, где требуется версия продукта:

System.IO.File.GetLastWriteTime(System.Reflection.Assembly.GetExecutingAssembly().Location).ToString("yyyy.MM.dd.HH.mm.ss")

Вместо того, чтобы пытаться получить версию из следующего:

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
object[] attributes = assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyFileVersionAttribute), false);
object attribute = null;

if (attributes.Length > 0)
{
    attribute = attributes[0] as System.Reflection.AssemblyFileVersionAttribute;
}

[Visual Studio 2017, свойства .csproj ]

Чтобы автоматически обновить свойство PackageVersion / Version / AssemblyVersion (или любое другое свойство), сначала создайте новый Microsoft.Build.Utilities.Task класс, который получит ваш текущий номер сборки и отправит обратно обновленный номер (я рекомендую создать отдельный проект только для этого класса).

Я вручную обновляю номера major.minor, но позволяю MSBuild автоматически обновлять номер сборки (1.1. 1 , 1.1. 2 , 1.1. 3 и т. Д. :)

using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
using System.Text;

public class RefreshVersion : Microsoft.Build.Utilities.Task
{
    [Output]
    public string NewVersionString { get; set; }
    public string CurrentVersionString { get; set; } 

    public override bool Execute()
    {       
        Version currentVersion = new Version(CurrentVersionString ?? "1.0.0");

        DateTime d = DateTime.Now;
        NewVersionString = new Version(currentVersion.Major, 
            currentVersion.Minor, currentVersion.Build+1).ToString();
        return true;
    }

}

Затем вызовите недавно созданную задачу в процессе MSBuild, добавив следующий код в файл .csproj:

<Project Sdk="Microsoft.NET.Sdk">    
...
<UsingTask TaskName="RefreshVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\<dll path>\BuildTasks.dll" />
<Target Name="RefreshVersionBuildTask" BeforeTargets="Pack" Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
   <RefreshVersion CurrentVersionString="$(PackageVersion)">
          <Output TaskParameter="NewVersionString" PropertyName="NewVersionString" />             
   </RefreshVersion>
   <Message Text="Updating package version number to $(NewVersionString)..." Importance="high" />
   <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\mustache.website.sdk.dotNET.csproj" Query="/Project/PropertyGroup/PackageVersion" Value="$(NewVersionString)" />
</Target>
...
<PropertyGroup>
 ..
 <PackageVersion>1.1.4</PackageVersion>
 ..

При выборе варианта проекта Visual Studio Pack (просто измените значение на BeforeTargets="Build" для выполнения задачи перед сборкой) код RefreshVersion будет запущен для вычисления нового номера версии, и XmlPoke задача соответственно обновит ваше свойство .csproj (да, он изменит файл).

При работе с библиотеками NuGet я также отправляю пакет в репозиторий NuGet, просто добавляя следующую задачу сборки в предыдущий пример.

<Message Text="Uploading package to NuGet..." Importance="high" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)\bin\release" Command="c:\nuget\nuget push *.nupkg -Source https://www.nuget.org/api/v2/package" IgnoreExitCode="true" />

c:\nuget\nuget это то место, где у меня есть клиент NuGet (не забудьте сохранить ключ API NuGet, позвонив nuget SetApiKey <my-api-key> или включив ключ в push-вызов NuGet).

На всякий случай кому-то поможет ^ _ ^.

Вот альтернативный вариант, сделанный вручную: это быстрый и грязный фрагмент PowerShell, который я написал, который вызывается на этапе предварительной сборки в нашей системе сборки Jenkins.

Он устанавливает последнюю цифру AssemblyVersion и AssemblyFileVersion в значение BUILD_NUMBER переменной среды, которая автоматически устанавливается системой сборки.

if (Test-Path env:BUILD_NUMBER) {
    Write-Host "Updating AssemblyVersion to $env:BUILD_NUMBER"

    # Get the AssemblyInfo.cs
    $assemblyInfo = Get-Content -Path .\MyShinyApplication\Properties\AssemblyInfo.cs

    # Replace last digit of AssemblyVersion
    $assemblyInfo = $assemblyInfo -replace 
        "^\[assembly: AssemblyVersion\(`"([0-9]+)\.([0-9]+)\.([0-9]+)\.[0-9]+`"\)]", 
        ('[assembly: AssemblyVersion("$1.$2.$3.' + $env:BUILD_NUMBER + '")]')
    Write-Host  ($assemblyInfo -match '^\[assembly: AssemblyVersion')
        
    # Replace last digit of AssemblyFileVersion
    $assemblyInfo = $assemblyInfo -replace 
        "^\[assembly: AssemblyFileVersion\(`"([0-9]+)\.([0-9]+)\.([0-9]+)\.[0-9]+`"\)]", 
        ('[assembly: AssemblyFileVersion("$1.$2.$3.' + $env:BUILD_NUMBER + '")]')
    Write-Host  ($assemblyInfo -match '^\[assembly: AssemblyFileVersion')
        
    $assemblyInfo | Set-Content -Path .\MyShinyApplication\Properties\AssemblyInfo.cs -Encoding UTF8
} else {
    Write-Warning "BUILD_NUMBER is not set."
}

Какую систему управления версиями вы используете?

Почти все они имеют ту или иную форму тега $ Id $, который расширяется при возврате файла.

Я обычно использую какую-либо форму хакерства, чтобы отобразить это как номер версии.

Другой вариант - использовать дату в качестве номера сборки: 080803-1448.

Некоторое время назад я написал быстрый и грязный exe, который обновлял версию # в файле assemblyinfo. {Cs / vb} - я также использовал rxfind.exe (простой и мощный инструмент замены поиска на основе регулярных выражений) для выполнения обновление из командной строки как часть процесса сборки. Еще пара полезных советов:

  1. разделите информацию о сборке на части продукта (название компании, версия и т. д.) и детали, относящиеся к сборке (название сборки и т. д.). Смотрите здесь
  2. Кроме того, я использую Subversion, поэтому я счел полезным установить номер сборки на номер версии Subversion, что позволяет очень легко всегда возвращаться к кодовой базе, которая сгенерировала сборку (например, 1.4.100.1502 был построен из ревизии 1502).

VS.NET по умолчанию устанавливает версию сборки 1.0. * И использует следующую логику при автоматическом увеличении: он устанавливает часть сборки на количество дней с 1 января 2000 года и устанавливает часть ревизии на количество секунд с полуночи, местное время, разделенное на два. См. Эту статью MSDN .

Версия сборки находится в файле assemblyinfo.vb или assemblyinfo.cs. Из файла:

' Version information for an assembly consists of the following four values:
'
'      Major Version
'      Minor Version 
'      Build Number
'      Revision
'
' You can specify all the values or you can default the Build and Revision Numbers 
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> 

<Assembly: AssemblyVersion("1.0.0.0")> 
<Assembly: AssemblyFileVersion("1.0.0.0")> 

Если вам нужно автоматически увеличивающееся число, которое обновляется каждый раз при выполнении компиляции, вы можете использовать VersionUpdater из события перед сборкой. Событие перед сборкой может проверить конфигурацию сборки, если вы предпочитаете, чтобы номер версии увеличивался только для сборки выпуска (например).