Привет!
В связи со сложностью проекта, над которым я сейчас работаю, появилась необходимость развертывания и настройки PostgreSQL на каждой машине клиента. Клиентов у нашей компании много, поэтому было решено автоматизировать процесс настройки PostgreSQL и создать MSI инсталлятор.
Недавно на хабре я прочитал переводную статью про Wix #, о нем и пойдет речь.
Как уже было сказано в статье, Wix # — это часть движка с открытым кодом, позволяющего выполнять C# скрипты.
После загрузки Wix # в архиве можно обнаружить множество примеров, начиная с простого копирования файлов и создания ярлыков на рабочем столе и заканчивая собственными диалогами для инсталлятора на WPF.
Задача состоит в следующем:
На первых двух пунктах подробно останавливаться не будем, все есть в примерах. Для настройки СУБД требуется заменить файл pg_hba.conf, импортировать базу данных из сохраненной копии. Все это нужно сделать без участия пользователя, запустившего инсталлятор.
Первым делом создаем простой инсталлятор для разворачивания проекта. Далее расскажу как сделать такой инсталлятор на примере Visual Studio, хотя это совсем необязательно — можно использовать любой текстовый редактор.
Cоздаем простое консольное приложение на C#,
и устанавливаем для решения WixSharp через менеджер проектов NuGet.
Перед началом установки пользователю обычно предлагается несколько компонентов для инсталляции на выбор, в Wix# для этого существует объект Feature.
Создаем компоненты для установки,
Feature fSoftware = new Feature("<Ваше ПО>");
Feature fPostgreSQL = new Feature("Настройка PostgreSQL");
// у этого объекта много разных интересных свойств,
// например, их можно сделать вложенными и тд, добавим описания
fSoftware.Description = "Установка программного обеспечения";
fPostgreSQL.Description = "Установка и настройка PostgreSQL";
В Wix# существуют разные объекты для построения проектов, например, Project или ManagedProject. Последний отличается тем, что к нему можно добавить свой код на C#, который будет выполнен в процессе установки.
Определим каталог, где будут находиться файлы, включенные в пакет инсталлятора.
var filesPath =Path.Combine(
Path.GetFullPath(
Path.Combine(System.Reflection.Assembly
.GetExecutingAssembly().Location, @"......")), "Files");
Создаем объект проекта и описываем необходимые файлы для установки.
var project = new ManagedProject("Название вашего ПО",
// Id не обязателен, но может пригодиться
// если использовать Custom Actions и тп
new Dir(new Id("INSTALL_DIR"), @"%ProgramFiles%<Ваше ПО>",
// копируем все файлы из папки с устанавливаемым ПО
new Files(fSoftware, Path.Combine(
filesPath, @"<Папка с файлами вашего ПО>*.*"))),
// PostgreSQL будем устанавливать в папку С:PostgreSQL
// (можно выбрать любую другую)
// установщик должен лежать в папке с файлами для установки
new Dir("C:PostgreSQL",
// копируем установщик
new WixSharp.File(fServer,
Path.Combine(filesPath, @"postgresqlwin.exe")),
// дамп БД
new WixSharp.File(fServer,
Path.Combine(filesPath, @"database.backup")),
// настройки конфигурации
new WixSharp.File(fServer,
Path.Combine(filesPath, @"pg_hba.conf")),
// BAT-файл (см ниже)
new WixSharp.File(fServer,
Path.Combine(filesPath, @"installDB.bat")))
);
Для того, чтобы произвести различные действия после или во время установки в Wix# существуют богатые возможности — например, если необходимо установить ReportViewer, то в тело проекта необходимо добавить:
new InstalledFileAction("ReportViewer.exe", "/q", Return.asyncNoWait, When.After, Step.InstallFinalize, Condition.NOT_Installed)
Для установки и настройки PostgreSQL можно так же использовать InstalledFileAction и другие, но из-за множества команд, которые необходимо выполнить, решено сделать BAT-файл InstallDB.bat:
# устанавливаем пароль в переменной среды для PostgreSQL
SET PGPASSWORD=123456
# добавляем базу данных
C:PostgreSQLbincreatedb.exe --host localhost --port 5432 --username "postgres" --no-password <Имя Вашей БД>
# импортируем БД
C:PostgreSQLbinpg_restore.exe --host localhost --port 5432 --username "postgres" --dbname "Имя Вашей БД" --role "postgres" --no-password --verbose "C:PostgreSQLdatabase.backup"
Далее проект необходимо настроить:
project.ControlPanelInfo.Manufacturer = "<Название Вашей компании>";
project.GUID = new Guid("{F1CC4E21-0326-4107-BB5C-A834EAEF6DAE}");
project.LicenceFile = Path.Combine(filesPath, @"License.rtf");
project.UI = WUI.WixUI_Mondo;
project.Language = "ru-RU";
project.OutFileName = "SetUp";
// проверка на .Net Framework 4.0
project.SetNetFxPrerequisite("NETFRAMEWORK40FULL >= '#1'",
"Пожалуйста, установите .NET Framework 4.0.");
project.PreserveTempFiles = true;
project.DefaultFeature = fSoftware;
project.Version = new Version("1.0.0.1");
project.AfterInstall += AfterInstall;
Compiler.BuildMsi(project);
Теперь для события AfterInstall можно написать Custom Action для запуска установки и настройки PostgreSQL:
private static void AfterInstall(SetupEventArgs e)
{
try
{
if ((e.Mode == SetupEventArgs.SetupMode.Installing) || (e.Mode == SetupEventArgs.SetupMode.Modifying))
{
if (System.IO.File.Exists(@"C:PostgreSQLpostgresqlwin.exe"))
{
var process = new Process();
process.StartInfo = new ProcessStartInfo(@"C:PostgreSQLpostgresqlwin.exe", @"--prefix C:PostgreSQL --mode unattended --datadir C:PostgreSQLdata --superpassword 123456 --install_runtimes 0");
process.Start();
process.WaitForExit();
System.IO.File.Delete(@"C:PostgreSQLpostgresqlwin.exe");
}
if (System.IO.File.Exists(@"C:PostgreSQLpg_hba.conf"))
{
System.IO.File.Copy(@"C:PostgreSQLpg_hba.conf", @"C:PostgreSQLdatapg_hba.conf", true);
System.IO.File.Delete(@"C:PostgreSQLpg_hba.conf");
}
if (System.IO.File.Exists(@"C:PostgreSQLdatabase.backup"))
{
if (System.IO.File.Exists(@"C:PostgreSQLinstallDB.bat"))
{
var pgProcess = new Process();
pgProcess.StartInfo = new ProcessStartInfo(@"C:PostgreSQLinstallDB.bat", "")
{
CreateNoWindow = true,
UseShellExecute = false
};
pgProcess.Start();
pgProcess.WaitForExit();
System.IO.File.Delete(@"C:PostgreSQLinstallDB.bat");
}
else
return;
System.IO.File.Delete(@"C:PostgreSQLdatabase.backup");
}
}
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(" Ошибка установки: " + ex.ToString());
}
}
Как вариант, можно было бы скопировать установщик PostgreSQL во временную папку и запускать установку из нее.
При помощи таких простых действий PostgreSQL будет автоматически настроен для вашего ПО.
Однако, есть моменты, которые в Wix# мне не понравились:
1) Поддержка только .NET Framework 3.5
2) Вообще в Wix — невозможно запустить установщик MSI из своего установщика, для этого нужно использовать расширения WIX, что усложняет задачу. Именно поэтому ReportViewer пришлось устанавливать после завершения установки.
3) Почему то возникает проблема с таким кодом:
new Dir(@"C:Test1", ..файлы),
new Dir(@"C:Test2", ..файлы)
Не собирается, выдается ошибка о недопустимом пути. Если оставить только одну папку, то все работает.
Следующий код работает, но частично:
new Dir(@"C:Test",
new Dir(@"Test1", файлы для feature1),
new Dir(@"Test2", файлы для feature2),
)
По идее, в каталоги Test1 и Test2 должны быть скопированы файлы, что и происходит, если при установке выбрать feature1 и feature2.
А если при установке выбрать только feature1, а затем добавить feature2 (Изменить установку), то папки Test2 не появится — вместо нее будет папка ABSOLUTEPATH с файлами для feature2.
Наверняка в моем скрипте что-то не было учтено.
В целом, Wix# мне понравился, особенно, если необходимо быстро сделать инсталлятор, не погружаясь в XML для WIX.
Источники:
Автор: AntonioGrande