2014-09-24 3 views
2

Я пытаюсь построить на этот вопрос:Как автоматически вставить номер версии в AssemblyName

Reading a single value from a file in MSBuild

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

Основываясь на вышеприведенном вопросе, у меня уже есть первая часть, но у меня возникли трудности со второй частью и я бы оценил некоторые рекомендации.

В моем решении, я создал обычный текстовый файл с именем VERSION.TXT, содержащий мой полный номер версии только:

1.1.0.0

В обоих моих проектов, я открыл свои AssemblyInfo.cs файлы и удалили элементы AssemblyVersion и AssemblyFileVersion, а затем модифицировали оба проекта, чтобы сгенерировать их в отдельном файле, как описано выше.

<ItemGroup> 
    <VersionFile Include="..\Version.txt" /> 
</ItemGroup> 
<Target Name="BeforeBuild"> 
    <ReadLinesFromFile File="@(VersionFile)"> 
     <Output TaskParameter="Lines" PropertyName="VersionNumber" /> 
    </ReadLinesFromFile> 
    <Delete Files="Properties\Version.cs" /> 
    <WriteLinesToFile File="Properties\Version.cs" Lines="using System.Reflection%3B&#xD;&#xA;&#xD;&#xA;[assembly: AssemblyVersion("$(VersionNumber)")]&#xD;&#xA;[assembly: AssemblyFileVersion("$(VersionNumber)")]" /> 
</Target> 

Теперь, когда я строю, я получаю сгенерированный Properties \ Version.cs файл для каждого проекта, который используется для создания EXE/DLL и показывается как «1.1.0.0» в их свойствах файла. Это именно то, чего я хочу.

Для DLL я хотел бы назвать сборку «filename.v1.1.dll», где «1.1» поступает из первых двух компонентов в Version.txt выше. Я гибкий в формате Version.txt, пока я могу получить полный «1.1.0.0» в свойствах EXE/DLL и «1.1» в имени DLL-файла.

Чтобы попробовать это, я изменил файл csproj в DLL, чтобы иметь:

<RootNamespace>dllfile</RootNamespace> 
<AssemblyName>dllfile.v$(VersionNumber)</AssemblyName> 

Конечно, это будет ввести полный номер версии в имени файла, который я не хочу.

Есть ли у кого-нибудь советы о том, как действовать?

Спасибо.

EDIT: Я был в состоянии извлечь основные/второстепенные компоненты номера версии, добавив следующую строку в моей .csproj цели BeforeBuild:

<ReadLinesFromFile File="@(VersionFile)"> 
    <Output TaskParameter="Lines" PropertyName="VersionNumber" /> 
</ReadLinesFromFile> 
<PropertyGroup> 
    <VersionNumberFirstDotIndex>$(VersionNumber.IndexOf('.'))</VersionNumberFirstDotIndex> 
    <VersionNumberMajorStart>0</VersionNumberMajorStart> 
    <VersionNumberMajorLen>$(VersionNumberFirstDotIndex)</VersionNumberMajorLen> 
    <VersionNumberMinorStart>$([MsBuild]::Add(1, $(VersionNumberFirstDotIndex)))</VersionNumberMinorStart> 
    <VersionNumberSecondDotIndex>$(VersionNumber.IndexOf('.', $(VersionNumberMinorStart)))</VersionNumberSecondDotIndex> 
    <VersionNumberMinorLen>$([MSBuild]::Subtract($([MSBuild]::Subtract($(VersionNumberSecondDotIndex), $(VersionNumberFirstDotIndex))), 1))</VersionNumberMinorLen> 
    <VersionNumberMajor>$(VersionNumber.Substring($(VersionNumberMajorStart), $(VersionNumberMajorLen)))</VersionNumberMajor> 
    <VersionNumberMinor>$(VersionNumber.Substring($(VersionNumberMinorStart), $(VersionNumberMinorLen)))</VersionNumberMinor> 
    <VersionNumberShort>$(VersionNumberMajor).$(VersionNumberMinor)</VersionNumberShort> 
</PropertyGroup> 
<Message Text="DEBUG1 VersionNumberFull=$(VersionNumber)" Importance="High" /> 
<Message Text="DEBUG2 VersionNumberAbbrev=$(VersionNumberShort)" Importance="High" /> 
<Delete Files="Properties\Version.cs" /> 
<WriteLinesToFile File="Properties\Version.cs" Lines="using System.Reflection%3B&#xD;&#xA;&#xD;&#xA;[assembly: AssemblyVersion(&quot;$(VersionNumber)&quot;)]&#xD;&#xA;[assembly: AssemblyFileVersion(&quot;$(VersionNumber)&quot;)]" /> 

Единственная часть теперь я недостающей как получить этот VersionNumberShort в имя DLL-файла. Если кто-то не имеет лучшее представление о том, что я могу принять предложение и использование Move задач Питера:

<Target Name="AfterBuild"> 
    <Move SourceFiles="$(OutputPath)$(AssemblyName).pdb" DestinationFiles="$(OutputPath)$(AssemblyName).v$(VersionNumberShort).pdb" /> 
    <Move SourceFiles="$(OutputPath)$(AssemblyName).dll" DestinationFiles="$(OutputPath)$(AssemblyName).v$(VersionNumberShort).dll" /> 
</Target> 
<Target Name="AfterClean" DependsOnTargets="Common"> 
    <Delete Files="$(OutputPath)$(AssemblyName).v$(VersionNumberShort).pdb" ContinueOnError="true" /> 
    <Delete Files="$(OutputPath)$(AssemblyName).v$(VersionNumberShort).dll" ContinueOnError="true" /> 
</Target> 

Поскольку я нуждался в одни и те же определения свойств, как и раньше, я переместил выше фрагмент кода в «Общие» цели и ссылки его в обоих построенные и чистые задачи, показанные здесь.

Peter - Если вы хотите переместить свой комментарий в качестве ответа, я соглашусь с ним.

Спасибо!

EDIT: После ответа jdlugosz я попытался установить AssemblyName внутри моей задачи.К сожалению, это до сих пор, кажется, не имеют никакого эффекта на основе исходного примера, указанного в верхней:

<Target Name="BeforeBuild"> 
    ... 
    <WriteLinesToFile ... /> 
    <PropertyGroup> 
     <AssemblyName>dllfile.v$(VersionNumber)</AssemblyName> 
    </PropertyGroup> 
</Target> 

Я попытался запустить это с MSBuild из командной Visual Studio Developer Prompt:

msbuild /target:clean projfile.csproj 
msbuild /verbosity:diag projfile.csproj > out.txt 

До этого я переименовал верхнюю часть моего файла csproj и в «переопределении» к чему-то уникальному, чтобы упростить поиск (например, «dllfileoriginal» и «dllfilemodified»).

Просмотрев выходной журнал, я не могу найти ссылку на измененный текст; он все еще dllfileoriginal везде на выходе.

После задачи WriteLinesToFile, похоже, были построены следующие цели:

  • IncrementalClean (законченный)
  • PostBuildEvent
  • CoreBuild
  • AfterBuild
  • Построить

Нет ссылки на ei это имя DLL внутри них.

Похоже, на данный момент мой лучший выбор.

+1

Почему бы не добавить элемент в конце цели или цель AfterBuild, чтобы переименовать двоичный файл? –

+0

@PeterRitchie - он не будет работать, если сборка будет подписана. Плюс вопрос в том, чтобы построить этот новый путь, меньше, когда это сделать ... –

+1

Почему вы хотите версию в имени сборки? Какую пользу вы получаете от этого? –

ответ

0

Целевое имя отображается на странице «Общие» на вкладке «Свойства конфигурации» в редакторе страницы свойств IDE. У меня нет одного удобного для поиска имени для вас, но вы можете сделать это, изменив пробел в IDE на что-то вроде XXXX и сохраните. Затем просмотрите diff в редакторе проверки выполнения версии и посмотрите, что такое имя свойства. В этом случае, а затем изменить строку, чтобы изменить XXXX на $(OutputPath)$(AssemblyName).v$(VersionNumberShort)

enter image description here

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

Что я делаю для версий, передавая фрагменты через #defines как аргументы командной строки /D. Наверное, у вас нет этого на C#, хотя, IIRC.

+0

Боюсь, я не могу найти вкладку «Общие». Я посмотрел как на страницы свойств проекта, так и на панель «Свойства» в Visual Studio 2012. FormatVersion выглядит так, что он будет добавлять числа вместе в соответствии со страницей MSDN, а не разделить их. Я тоже думал об определении; Я считаю, что C# поддерживает их передачу, но мне не нужно ничего делать с ними в исходном файле, так как я уже сгенерировал файл Version.cs с помощью WriteLinesToFile, но это похоже на другую полезную идею. Благодарю. – jia103

+0

@ jia103 Я уточнил местоположение в ответе выше. –

+0

Спасибо за обновление. Этот экран выглядит знакомым; похоже, что вы используете другую версию Visual Studio; Я нахожусь в 2012 году, и я этого не вижу. Я также не вижу ничего подобного в файле .csproj; все, что у меня есть, есть . – jia103

0

Это работает для меня, и это решает, казалось бы, простую проблему добавления строки информации версии в имя файла при сборке.

Во-первых, событие после сборки:

(Щелчок правой кнопкой мыши проект -> Свойства -> Build Events -> Edit Post-билд ...)

$(TargetPath) "version" > $(TargetDir)text.txt 
set /p version= <$(TargetDir)text.txt 
copy $(TargetPath) $(TargetDir)$(TargetName)_%version%.exe 
del $(TargetDir)text.txt 

Теперь, трюк: Перегрузка sub main, чтобы вернуть информацию о версии, и вызвать ее в событии после сборки на exe, который был только что построен.

вот пример в F #:

[<EntryPoint>] 
let main argv = 

    let version = argv.Length = 1 && argv.[0] = "version" 
    if version then 
     let version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() 
     do stdout.WriteLine(version) 
     do stdout.Flush() 
    else 
     try 
     //... 

Событие после сборки выше

1) называет недавно построенный ехе с «версией» арг и записывает вывод в текстовый файл

2) считывает содержимое текстового файла в локальную переменную

3) переименовывает недавно построенный ехе, добавив информацию о версии

3) копирует недавно построенный ехе, добавив информацию о версии на имя

4) очищает временный файл

* изменилось «движение», чтобы «копировать», так что Visual Studio может еще F5 проект

Смежные вопросы