ClickOnce, WPF, MSBuild и несколько окружений — II

Подготовка к трансформации проекта

Чтобы у нас все получилось, потребуется скачать и установить на машине билд-сервера MSBuild Community Tasks Project, так же советую его поставить и на своей машине, для экспериментов и быстрого доступа к файлу справки. Данный пакет позволяет обращаться к реализации массы наиболее часто востребованных функций во время преобразований в процессе построения приложения с помощью MSBuild. Пакет устанавливается по адресу C:\Program Files (x86)\MSBuild\MSBuildCommunityTasks, это чтобы вы быстро нашли справку по новым доступным задачам.

Канон

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

MSBuild при сборке проекта руководствуется сложным набором правил и указаний, которые мы можем модифицировать или дополнять. Основные указания о сборке проекта содержаться в файле Common.CSharp.targets – который менять каким-либо образом крайне не рекомендуется. По принятому соглашению, все дополнения и расширения, касающиеся построения приложений должны иметь расширение .targets, по сути это XML файл.

Итак, нам придется:

  • немного модифицировать файл проекта .csproj
  • создать новый файл .targets

Начнем с создания нового файла в корне исполняемого проекта, в котором будем изменять параметры построения и публикации нашего приложения. Файл можете назвать как угодно, я назвал Publishing.targets. В начало файла следует скопировать определение проекта из файла .csproj того проекта, который вы будете публиковать. Т.е. открываю файл Accounting.csproj в Notepad++, и копирую узел объявления проекта в новый файл. В итоге в файле Publishing.targets должно быть что-то в духе:

 

Сохраняем и начинаем вносить изменения в исполняемый проект. Надо внести ссылки на MSBuild Community Task Project и на наш новый файл.

Открываем файл проекта, перемещаемся вниз файла, находим тэги Imports и дописываем там свои две строчки:

Указываем путь до нового файла, имя напишите свое, путь относительный от проекта, и указываем путь до расширений MSBuild – тут ничего менять не надо по идее. Пробуем собрать проект из командной строки, все должно быть хорошо для конфигураций Release и Prod. Для тех разработчиков, у которых не стоит MSBuild Community Task Project проект не соберется и будет просить установить недостающие библиотеки. Чтобы этого избежать сделаем включение задач из MSBuild CTP опциональным, для всех конфигураций кроме Debug.

 

Создание страницы публикации

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

Не буду тут приводить полный текст файла publish.htm, лучше его скачать здесь. Затем можете отредактировать его на свой вкус: перевести, дополнить информацией или удалить лишние пункты. Главное оставить/добавить уникальные идентификаторы для последующей замены во время публикации.

Отредактированный файл надо включить в проект, я создал папку Publish и поместил туда publish.htm

О том, как заменять значения в этом файле речь пойдет чуть ниже.

Трансформация данных публикации

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

Замена значений по условию

Наверно, это самый важный момент для того, чтобы приложение для разных окружений воспринималось клиентом как две разных программы. Сейчас будем устанавливать значения для окружения QA и PROD. Данные значения будут размещены в файле Publishing.targets.

Открываем файл и сразу за открытием тега Project вставляем код, все вместе должно выглядеть так:

Данная секция описывает условный переход и присвоение значений переменным, которые будем использовать далее. Choose – контейнер для описания условий, далее используется тег When в котором описывается условие для входа. В данном случае условие накладывается на значение конфигурации. Вам надо выставить свои значения в условии.

Далее идет тег PropertyGroup –он открывает секцию с объявлением переменных, так же в этой секции можно переписывать значения переменных.  В этой секции ключевыми переменными являются:

  • ArmApplicationId – можете придумать свое имя, мы специально вводим эту переменную для модификации файла Accounting.application который является конфигурацией опубликованного приложения.
  • ProductName – это существующее имя для имени продукта.

Описанные переменные должны иметь различные значения для каждой конфигурации.

Прошу заметить, что  значение переменной ArmApplicationId заключено в кавычки.

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

Замены для страницы опубликованного приложения

Теперь можно подготовиться к окончательному формированию страницы опубликованного приложения publish.htm. Нам надо провести замены «переменных» в файле  publish.htm, для этого продолжаем дописывать файл Publishing.targets и вставляем следующий код после секции Choose.

В данных заменах пока что нет версии приложения. Это скоро будет исправлено.

В действии

Собственно сейчас осталось только указать время, когда производить указанные замены. Для этого можно переопределить несколько событий (в терминологии MSBuild — Targets), сейчас же нам понадобиться только AfterPublish.

В описании этого события мы внесем последние изменения в страницу приложения, опубликуем страницу, а так же сделаем так, чтобы для клиента опубликованные приложения CONS и PROD были разными программами.

Прежде чем указать действия для AfterPublish, надо создать переменную для публикации файла publish.htm

Разместите этот код в конце файла Accounting.targets перед закрывающим тегом </Project>.

Следующим шагом будет реализация AfterPublish:

Первой строкой идет указание того, когда это будет выполнено – AfterPublish  – зарезервированное имя, доступное к переопределению.  Далее идет использование задачи Time из пакета MSBuild Community Task, с помощью этой задачи будем указывать время публикации на странице publish.htm.

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

Следующие две задачи опять из пакета MS Build Community Task и позволяют заменять значения в файлах. По структуре вы можете догадаться о работе данной задачи. В нашем случае мы выставляем время публикации, а так же делаем уникальным идентификатор приложения, по которому (совместно с ProductName) клиент будет думать, что у него разные приложения.

Можно снова попробовать опубликовать приложение с разными настройками конфигурации и установить их у себя. Вы увидите, что установилось два приложения: QA (Cons) и PROD. Они работают независимо и не мешают работе друг друга.

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

Создание версий

Как вы могли прочитать или заметить на собственном опыте, версия приложения и опубликованная версия – это две совершенно разных версии, однако желательно привести их в соответствие. Версия приложения хранится в AssemblyInfo.cs, версия публикации — в файле *.publish (это по версии интернетов, однако я не смог найти этот файл, так что для меня загадка, где хранится номер опубликованной версии.)

С помощью задач из пакета MSBuild CTP можно создать свой файл AssemblyInfo.cs в котором писать номер версии до того, как проект начнет собираться.

По условию задачи становится понятно, что надо искать и модифицировать цель\задачу (targets) с назаванием BeforeBuild. Эту задачу можно найти в конце файла .csproj для публикуемого проекта. Задача закомментирована, так что вы можете удалить комментарий и внести следующий код в задачу:

Первым делом надо снять метку ReadOnly с файла AssemblyInfo.cs. Это делается с помощью задачи Attrib. Далее используем задачу Time из пакета дополнений к MSBuild, и формируем новые переменные из значений, которые могут быть предоставлены задачей Time. Для нас актуальны: часы и порядковый день года. Тег Output заполняет переменные.

Далее идет формирование файла AssemblyInfo, где формируется версия приложения и сборки. Так как сборка идет на MSBuild 4.0, то можно использовать вызовы к стандартным библиотекам.

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

После того, как создали новый файл AssemblyInfo.cs записываем значения новой версии в переменные:

  • ApplicationVersion –версия публикации
  • ApplicationVersionPublishPage – для отображения на странице публикации

После того, как указали все действия на момент сборки, осталось внести финальные изменения в файл Publishing.targets. Надо внести изменения для использования ApplicationVersionPublishPage.

Внесите этот кусок кода до определения задачи AfterPublish.

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

 

Заключение

Надеюсь, что у вас получится изменить  проекты  для публикации с первого раза и без привлечения сторонних источников. Буду рад любым отзывам и заметкам, по поводу неочевидных моментов в этой статье.

 

PDF версия

 

Hard’n’heavy!

 

Оставить комментарий