Определение версии сборки во время события после сборки

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

Я надеялся, что смогу использовать событие post-build и передать номер версии в пакетный файл следующим образом:

 call foo.bat $(AssemblyVersion) 

Однако я не могу найти подходящую переменную или макрос для использования.

Есть ли способ достичь этого, которого я пропустил?

Если вы предпочитаете писать сценарии, эти методы могут также работать на вас:

Если вы используете событие post-build, вы можете использовать инструмент filever.exe, чтобы извлечь его из уже построенной сборки:

 for /F "tokens=4" %%F in ('filever.exe /B /A /D bin\debug\myapp.exe') do ( set VERSION=%%F ) echo The version is %VERSION% 

Найдите файл filever.exe здесь: http://support.microsoft.com/kb/913111

Если вы используете событие pre-build, вы можете извлечь его из файла AssemblyInfo.cs следующим образом:

 set ASMINFO=Properties\AssemblyInfo.cs FINDSTR /C:"[assembly: AssemblyVersion(" %ASMINFO% | sed.exe "s/\[assembly: AssemblyVersion(\"/SET CURRENT_VERSION=/g;s/\")\]//g;s/\.\*//g" >SetCurrVer.cmd CALL SetCurrVer.cmd DEL SetCurrVer.cmd echo Current version is %CURRENT_VERSION% 

Это использует инструмент командной строки unix sed, который вы можете скачать из многих мест, например здесь: http://unxutils.sourceforge.net/ – iirc, который работает нормально.

Если (1) вы не хотите загружать или создавать пользовательский исполняемый файл, который извлекает версию сборки, и (2) вы не возражаете редактировать файл проекта Visual Studio, тогда есть простое решение, позволяющее использовать макрос который выглядит следующим образом:

@ (Targets -> ‘% (Version)’)

 @(VersionNumber) 

Для этого выгрузите проект. Если проект где-то определяет свойство , вырезать его из проекта и временно сохранить его в другом месте (блокнот?). Затем в самом конце проекта, непосредственно перед конечным тегом, поместите это:

           $(PostBuildEventDependsOn); PostBuildMacros;  echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)  

В этом fragmentе уже есть пример . Не беспокойтесь, вы можете сбросить его на свое реальное событие после сборки после повторной загрузки проекта.

Теперь, как и было обещано, версия сборки доступна для вашего события post build с этим макросом:

 @(VersionNumber) 

Готово!

В качестве обходного пути я написал управляемое консольное приложение, которое принимает цель как параметр и возвращает номер версии.

Мне все еще интересно услышать более простое решение, но я отправляю его на тот случай, если кто-либо найдет его полезным.

 using System; using System.IO; using System.Diagnostics; using System.Reflection; namespace Version { class GetVersion { static void Main(string[] args) { if (args.Length == 0 || args.Length > 1) { ShowUsage(); return; } string target = args[0]; string path = Path.IsPathRooted(target) ? target : Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + Path.DirectorySeparatorChar + target; Console.Write( Assembly.LoadFile(path).GetName().Version.ToString(2) ); } static void ShowUsage() { Console.WriteLine("Usage: version.exe "); } } } 

Этот ответ является незначительной модификацией ответа Брент Ариас. Его PostBuildMacro отлично работал для меня до обновления версии Nuget.exe.

В последних выпусках Nuget обрезает несущественные части номера версии пакета, чтобы получить семантическую версию типа «1.2.3». Например, версия сборки «1.2.3.0» отформатирована Nuget.exe «1.2.3». И «1.2.3.1» отформатирован «1.2.3.1», как ожидалось.

Поскольку мне нужно вывести точное имя файла пакета, сгенерированное Nuget.exe, теперь я использую этот адаптированный макрос (протестирован в VS2015):

           $(PostBuildEventDependsOn); PostBuildMacros;  echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)  

UPDATE 2017-05-24: Я исправил регулярное выражение таким образом: «1.2.0.0» будет переведен на «1.2.0», а не «1.2», как ранее закодировано.


И чтобы ответить на комментарий Ehryk Apr, вы можете адаптировать регулярное выражение, чтобы сохранить только часть номера версии. В качестве примера, чтобы сохранить «Major.Minor», замените:

  

От

  

Я думаю, что самое лучшее, что вы можете сделать, это посмотреть, как MSBuild и MsBuild Extension Pack вы сможете редактировать файл решения, чтобы происходило событие post build и записывалось в ваш тестовый файл.

Если это слишком сложно, вы можете просто создать небольшую программу, которая проверяет все сборки в вашем выходном каталоге и выполняет их в post build, вы можете передать в выходной каталог с использованием имени переменной … например, в событии post build. ..

AssemblyInspector.exe “$ (TargetPath)”

 class Program { static void Main(string[] args) { var assemblyFilename = args.FirstOrDefault(); if(assemblyFilename != null && File.Exists(assemblyFilename)) { try { var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilename); var name = assembly.GetName(); using(var file = File.AppendText("C:\\AssemblyInfo.txt")) { file.WriteLine("{0} - {1}", name.FullName, name.Version); } } catch (Exception ex) { throw; } } } } 

Вы также можете передать местоположение текстового файла …

Я начал добавлять отдельный проект, который строит последний, и добавляет событие post build для этого проекта, который запускается сам. Затем я просто программным образом выполняю свои шаги для сборки сообщений.

Это делает намного проще делать такие вещи. Затем вы можете просто проверить атрибуты сборки любой сборки, которую хотите. Пока это работает довольно просто.

Из этого я понимаю …

Вам нужен генератор событий post build.

1. Шаг: Написание генератора

 /* * Author: Amen RA * # Timestamp: 2013.01.24_02:08:03-UTC-ANKH * Licence: General Public License */ using System; using System.IO; namespace AppCast { class Program { public static void Main(string[] args) { // We are using two parameters. // The first one is the path of a build exe, ie: C:\pathto\nin\release\myapp.exe string exePath = args[0]; // The second one is for a file we are going to generate with that information string castPath = args[1]; // Now we use the methods below WriteAppCastFile(castPath, VersionInfo(exePath)); } public static string VersionInfo(string filePath) { System.Diagnostics.FileVersionInfo myFileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); return myFileVersionInfo.FileVersion; } public static void WriteAppCastFile(string castPath, string exeVersion) { TextWriter tw = new StreamWriter(castPath); tw.WriteLine(@""); tw.WriteLine(@""); tw.WriteLine(@"MyApp - New version! Release " + exeVersion + " is available."); tw.WriteLine(@"" + exeVersion + ""); tw.WriteLine(@"http://www.example.com/pathto/updates/MyApp.exe"); tw.WriteLine(@"http://www.example.com/pathto/updates/MyApp_release_notes.html"); tw.WriteLine(@""); tw.Close(); } } } список /* * Author: Amen RA * # Timestamp: 2013.01.24_02:08:03-UTC-ANKH * Licence: General Public License */ using System; using System.IO; namespace AppCast { class Program { public static void Main(string[] args) { // We are using two parameters. // The first one is the path of a build exe, ie: C:\pathto\nin\release\myapp.exe string exePath = args[0]; // The second one is for a file we are going to generate with that information string castPath = args[1]; // Now we use the methods below WriteAppCastFile(castPath, VersionInfo(exePath)); } public static string VersionInfo(string filePath) { System.Diagnostics.FileVersionInfo myFileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); return myFileVersionInfo.FileVersion; } public static void WriteAppCastFile(string castPath, string exeVersion) { TextWriter tw = new StreamWriter(castPath); tw.WriteLine(@""); tw.WriteLine(@""); tw.WriteLine(@"MyApp - New version! Release " + exeVersion + " is available."); tw.WriteLine(@"" + exeVersion + ""); tw.WriteLine(@"http://www.example.com/pathto/updates/MyApp.exe"); tw.WriteLine(@"http://www.example.com/pathto/updates/MyApp_release_notes.html"); tw.WriteLine(@""); tw.Close(); } } } 

2. Шаг: использование его в качестве команды post build в нашей среде IDE

После того, как приложение работает удовлетворительно для вас:

В среде разработки IDE используйте следующую командную строку для событий пост-сборки.

 C:\Projects\pathto\bin\Release\AppCast.exe "C:\Projects\pathto\bin\Release\MyApp.exe" "c:\pathto\www.example.com\root\pathto\updates\AppCast.xml" 

Если у вас есть проект библиотеки, вы можете попробовать использовать утилиту WMIC (доступную в windowsх). Вот пример. Хорошо – вам не нужно использовать внешние инструменты.

 SET pathFile=$(TargetPath.Replace("\", "\\")) FOR /F "delims== tokens=2" %%x IN ('WMIC DATAFILE WHERE "name='%pathFile%'" get Version /format:Textvaluelist') DO (SET dllVersion=%%x) echo Found $(ProjectName) version %dllVersion% 

Мне нужно было именно это для автоматического помещения числа в файл readme в выходной папке. В конце концов, как показал Уинстон Смит, небольшой внешний инструмент – это очень хорошее решение, и у него есть то преимущество, что вы можете отформатировать его, как хотите.

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

 public class GetVerNum { static void Main(String[] args) { if (args.Length == 0) return; try { FileVersionInfo ver = FileVersionInfo.GetVersionInfo(args[0]); String version = "v" + ver.FileMajorPart.ToString() + "." + ver.FileMinorPart; if (ver.FileBuildPart > 0 || ver.FilePrivatePart > 0) version += "." + ver.FileBuildPart; if (ver.FilePrivatePart > 0) version += "." + ver.FilePrivatePart; Console.Write(version); } catch { } } } 

Мои события после сборки:

  "$(ProjectDir)\Readme\readme-header.txt" "$(ProjectDir)\Readme\GetVersionNumber.exe" "$(TargetPath)" >>"$(ProjectDir)\Readme\readme-header.txt" echo by Nyerguds>>"$(ProjectDir)\Readme\readme-header.txt" echo Build date: %date% %time% >> "$(ProjectDir)\Readme\readme-header.txt" echo.>>"$(ProjectDir)\Readme\readme-header.txt" copy /b "$(ProjectDir)\Readme\readme-header.txt" + "$(ProjectDir)\Readme\readme-body.txt" "$(TargetDir)\$(ProjectName).txt" 

Я поместил все файлы, генерирующие readme, в папку \ Readme \ моего проекта; приложение, содержащее вышеуказанный код, и «readme-body.txt», содержащий фактический материал readme.

  • Первая строка: создайте файл readme-header.txt в папке \ Readme \ моего проекта и поместите в нее имя программы. ( это трюк, который я нашел здесь: пакет Windows: эхо без новой строки ). Вы также можете сохранить эту строку в другом текстовом файле и просто скопировать ее в «readme-header.txt».
  • Вторая строка: запустите приложение для получения номера версии с только что созданным exe-файлом в качестве параметра и добавьте его вывод в файл заголовка.
  • Третья строка: добавить в файл заголовка любые другие вещи (в данном случае, кредиты). Это также добавляет разрыв строки до конца.

Эти три вместе дают вам файл «readme-header.txt» с «My Application v1.2.3 by Nyerguds», за которым следует разрыв строки. Затем я добавляю дату сборки и другую открытую строку и копирую файл заголовка и файл тела readme вместе с одним файлом в окончательной папке сборки. Обратите внимание, что я специально использую двоичную копию, иначе она дает нечетные результаты. Вы должны убедиться, что файл body не содержит отметки порядка байтов UTF-8 в начале, или вы получаете странные байты в конечном файле.

  • Запуск приложения на основе .net без .NET Framework
  • PhpStorm - преимущества редактирования развернутых файлов напрямую, а также загрузка и синхронизация
  • Какой метод вы используете для развертывания приложений ASP.Net в дикой природе?
  • Объединить msi и exe
  • Лучший способ развертывания приложения Visual Studio, которое может работать без установки
  • Как установить регистр переменной для сохранения между играми в недоступном?
  • Существует ли компилятор R?
  • Как найти полное имя сборки?
  • XamlParseException после развертывания проекта WPF
  • Ошибка развертывания Heroku H10 (приложение разбилось)
  • System.IO.FileNotFoundException: не удалось загрузить файл или сборку «X» или одну из ее зависимостей при развертывании приложения
  • Interesting Posts

    Фильтр выбора ffmpeg генерирует нежелательные черные рамки

    Получение android.content.res.Resources $ NotFoundException: исключение, даже если ресурс присутствует в android

    Тип для даты только в C # – почему нет типа даты?

    Использование двух значений для одного оператора case switch

    Как установить java 1.7 runtime на macos 10.9 mavericks?

    Могу ли я использовать Aero-привязку к верхнему / нижнему, а не влево / вправо при использовании режима портретного отображения для монитора?

    Как конвертировать дату в формат yyyy-MM-dd?

    Может ли Google Chrome открывать локальные ссылки?

    как установить режим выбора для списка с изображениями

    Принуждение нескольких streamов к использованию нескольких процессоров, когда они доступны

    по дате в mongodb

    Может ли эмулятор Android записывать и воспроизводить звук с помощью аппаратного обеспечения ПК?

    Должны ли получатели Java 8 возвращать дополнительный тип?

    Проблемы с Excel 2010 Функция «Найти», возвращающая значение #value

    Формула Excel для расчета продолжительности времени на основе строки текста, такой как 9:00 – 12:30

    Давайте будем гением компьютера.