Скажем, я хотел создать файл статического текста, который поставлется с каждым выпуском. Я хочу, чтобы файл был обновлен с номером версии выпуска (как указано в AssemblyInfo.cs
), но я не хочу должным быть делать это вручную.
Я надеялся, что мог использовать событие постсборки и подать номер версии к пакетному файлу как это:
call foo.bat $(AssemblyVersion)
Однако я не могу найти, что любая подходящая переменная или макрос используют.
Существует ли способ достигнуть этого, что я отсутствовал?
Если вы предпочитаете писать сценарии, эти методы также могут сработать для вас:
Если вы используете событие после сборки, вы можете использовать инструмент 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
Если вы используете событие предварительной сборки, вы можете извлечь его из файла 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, который работает нормально.
В качестве обходного пути я написал управляемое консольное приложение, которое принимает цель в качестве параметра и возвращает номер версии.
Мне все еще интересно услышать более простое решение, но я публикую его на случай, если кто-то еще сочтет его полезным.
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 <target>");
}
}
}
Думаю, лучшее, что вы можете сделать, - это посмотреть на MSBuild и MsBuild Extension Pack , чтобы вы могли редактировать свой файл решения, чтобы что происходит событие пост-сборки и записывается в ваш тестовый файл.
Если это слишком сложно, вы можете просто создать небольшую программу, которая проверяет все сборки в вашем выходном каталоге и запускать ее при сборке после сборки, вы можете передать в выходной каталог, используя имя переменной ... например, в сообщении событие сборки ...
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;
}
}
}
}
Вы также можете передать местоположение текстового файла ...
Я начал добавлять отдельный проект, который собирается последним, и добавлять событие после сборки в этот проект, который запускается сам по себе. Затем я просто программно выполняю свои шаги после сборки.
Такие вещи делать намного проще. Затем вы можете просто проверить атрибуты сборки любой сборки, которую вы хотите. Пока это работает довольно круто.