Сборка .msi-пакетов под Linux

Одно из моих поделий (https://github.com/bozaro/octobuild) для установки под Windows упаковывается в .msi-пакеты. И чтобы не держать для сборки Windows, я заморочился и разобрался, как собираться из под Windows.

Инструментарий для сборки MSI-пакетов

Для сборки .msi-пакетов я использую Wix (http://wixtoolset.org/).

Чтобы не возиться с написанием XML-файлов для Wix, я использую WixSharp (https://wixsharp.codeplex.com/).

WixSharp самодостаточен. Для сборки установочных пакетов ничего, кроме него устанавливать не нужно. Архив с WixSharp в том числе содержит и Wix.

Сборка .msi-пакетов крайне платформозависимая вещь. В результате я решил использовать Wine внутри Linux-контейнера. В качестве гостевой ОС использую Ubuntu 16.04.

Установка Wine

Установка Wine в Linux-контейнер оказалась не тривиальной. Основная проблема в том, что Wine активно использует 32-х битные библиотеки.

Для решения этой проблемы нужно добавить поддержку 32-х битной архитектуры:

sudo dpkg --add-architecture i386

После этого можно собственно установить Wine:

sudo apt install software-properties-common
sudo add-apt-repository ppa:ubuntu-wine/ppa
sudo apt update
sudo apt install wine1.8 winetricks

Установка .NET внутри Wine

Для начала, нужно установить .NET внутри Wine.

Используем в Wine 32-х битное окружений

.NET 4.0 в Wine поддерживается только в 32-х битном окружении.

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

# Используем 32-х битное окружение
export WINEARCH=win32
# Используем отдельный каталог для Wine
export WINEPREFIX=$HOME/.wine-i686/

Добавляем в контейнер поддержку GUI

Для установки .NET нужен GUI.

Самый простой способ получить доступ к GUI на удаленной машине: подключиться к ней по SSH с поддержкой X-сервера.

Это делается командой вида:

ssh -X remote-host

К сожалению, в контейнере по-умолчанию это не дало эффекта, так как там не установлен xauth.

Для исправления ситуации нужно установить xauth в контейнер:

sudo apt install xauth

Собственно установка .NET

Сама установка .NET выполняется командой:

winetricks dotnet40

При этом она попросит вручную скачать ряд файлов от Microsoft, но трудностей это у меня не вызвало.

Исправление ошибки: The specified user does not have a valid profile

System.IO.FileLoadException: The specified user does not have a valid profile.  Unable to load 'WixSharp, Version=1.0.34.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2'.
File name: 'WixSharp, Version=1.0.34.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2'

Эта ошибка у меня возникла из-за использования ManagedAction.

Лечится добавлением магического ключа в реестр:

wine reg add "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\S-1-5-21-0-0-0-1000"

Исправление ошибки: Unhandled exception 0xe0434352

System.IO.IOException: Неверный параметр.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.__Error.WinIOError()
   at System.Console.set_OutputEncoding(Encoding value)
   at csscript.CSExecutionClient.Main(String[] rawArgs)
wine: Unhandled exception 0xe0434352 in thread 9 at address 0x7b83ac1c (thread 0009), starting debugger...
err:winediag:nulldrv_CreateWindow Application tried to create a window, but no driver could be loaded.
err:winediag:nulldrv_CreateWindow Make sure that your X server is running and that $DISPLAY is set correctly.

Эта ошибка трепала нервы дольше остальных.

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

Полечилась она очень просто: достаточно было обновить файл cscs.exe, входящий в комплект WixSharp.

Так как у cscs.exe и WixSharp один автор, я попросил его обновить cscs.exe (https://wixsharp.codeplex.com/workitem/110).

В результате, с WixSharp v1.0.35.0 эта проблема более не актуальна.

Исправление ошибки: light.exe : error LGHT0216

light.exe : error LGHT0216 : An unexpected Win32 exception with error code 0x65B occurred: Сбой функции

Эта ошибка происходит из-за того, что Wine все-таки не до конца совместим с Windows. В данном конкретном случае Wix не может проверить создаваемый пакет.

Для обхода этой ошибки можно просто отключить проверку корректности пакетов, передав light.exe параметр -sval.

В случае с WixSharp это выглядит примерно так:

Project project = new Project("Test");
project.LightOptions = "-sval";
comments powered by Disqus