Wix Installer: установка свойства условия компонента при установке администратора MSIEXEC из командной строки
У нас есть три типа / разновидности нашего продукта, но только один MSI написан на WiX. Когда мы собираем установщик, мы передаем вкус через определенную константу:
Call MSBUILD.bat ..\MSIs\CoreProduct\OurProduct.sln /p:DefineConstants="FLAVOUR=%_Flavour%"
и константа настраивается в Visual Studio, под Build -> Define препроцессорными переменными как FLAVOR=50. Процесс сборки, принимает значения 50, 200 или LITE в качестве аромата.
В коде WiX у нас есть множество условий для наших компонентов, которые сообщают ему, какой файл устанавливать в зависимости от разновидности; например
<Component Id="cmp7F45920B1AA100729BAE37FC846B3FC5" Guid="*">
<File Id="fil238A776D9294E14671E012472F9F7196"
KeyPath="yes"
Source="$(var.MenusPath)\ClientListView 200.r5m"
<Condition>$(var.FLAVOUR)=200</Condition>
</Component>
<Component Id="cmp8BFF42B232724DC4BA5B8F87994DEF21" Guid="*">
<File Id="fil808D6428D67248DDB8CA65DBC5978283"
KeyPath="yes"
Source="$(var.MenusPath)\ClientListView Lite.r5m"
<Condition>$(var.FLAVOUR)=LITE</Condition>
</Component>
Таким образом, в приведенном выше примере будет установлен файл с именем "ClientListView Lite.r5m", если FLAVOR равен LITE, или будет установлен файл с именем "ClientListView 200.r5m", если FLAVOR равен 200.
Это все работает, как и ожидалось, и в течение многих лет!
Но теперь у нас есть веб-версия нашего продукта, и нам нужен zip-файл, содержащий структуру папок и файлы, которые будут установлены для каждого варианта. Я обнаружил, что вы можете запустить MSI в командной строке, используя MSIEXEC и аргумент /a, который затем перенаправит все, что было бы установлено в папку, и подумал, что это именно то, что я хочу... но, увы, это не работает, как я ожидал.
Кажется, что он выполняет MSI и извлекает файлы в целевую папку, но при этом игнорирует аромат, и в результате вы получаете файлы "ClientListView Lite.r5m" и "ClientListView 200.r5m", извлеченные в Папка; что явно не то, что я хочу.
После прочтения документации по MSIEXEC кажется, что вы можете передать значение для свойства Public, например msiexec.exe /a "C:\Example.msi" MY_PROP="myValue" - так что я подумал, что это может помочь мне; поэтому в своем коде WiX я добавил строку:
<Property Id='PRODTYPE' Value="$(var.FLAVOUR)"/>
и затем изменил условия моего компонента так:
<Component Id="cmp7F45920B1AA100729BAE37FC846B3FC5" Guid="*">
<File Id="fil238A776D9294E14671E012472F9F7196"
KeyPath="yes"
Source="$(var.MenusPath)\ClientListView 200.r5m"
<Condition><![CDATA[PRODTYPE=200]]></Condition>
</Component>
<Component Id="cmp8BFF42B232724DC4BA5B8F87994DEF21" Guid="*">
<File Id="fil808D6428D67248DDB8CA65DBC5978283"
KeyPath="yes"
Source="$(var.MenusPath)\ClientListView Lite.r5m"
<Condition><![CDATA[PRODTYPE=LITE]]></Condition>
</Component>
но хотя это скомпилировано нормально, запустив его через:
msiexec /a OurProduct.msi /qb PRODTYPE=200 TARGETDIR="C:\InstalledFiles200"
все еще извлекает оба файла для вкусов 200 & LITE, где я просто хотел получить один для 200.
Итак, я пытаюсь сделать что-то, что невозможно... или я делаю что-то не так - любая помощь будет с благодарностью, потому что альтернатива имитации процесса в пакетном файле для создания моего почтового индекса; будет ужасно!!
Ура,
Крис.
3 ответа
Ваше использование процессора
Я на полпути отвечал с предложением использовать конструкции препроцессора (?if?
и др.) Когда я понял, что вам нужен только один MSI (по крайней мере, за раз - кажется), я пропустил его. Обычно я использую такие конструкции для компиляции файлов MSI из того же источника WiX. Я выбросил то, что я написал ниже, с некоторой перефразировкой - без особого рассмотрения. Я проверю это позже.
Я мог бы что-то упустить в вашем случае, но я не понимаю, как ?if?
оператор может работать во время установки - это конструкция времени компиляции. Он предварительно обрабатывает ваш исходный файл WiX перед компиляцией и компоновкой. Таким образом, похоже, что вы на самом деле скомпилировали три разные версии MSI-файла, а затем запустили админ-установку для каждой из них? Если это так, то использование образа администратора не имеет значения, потому что весь ваш MSI не содержит ничего, кроме компонентов, которые вы включили в ?if?
- нет необходимости передавать какую-либо спецификацию свойства издания.
Настройка ароматов
Обычные технические подходы, которые я использую, когда мне нужно создать различные варианты настройки или редакции продукта, следующие:
Препроцессорные конструкции: используются для компиляции разных версий или версий (также разных языковых версий) MSI во время компиляции. Одна такая конструкция
?if?
заявление, которое вы упоминаете. Есть несколько других, как видно по ссылке выше. Соответствующими для вас будут условные высказывания (if
,ifdef
,ifndef
,else
,elseif
,endif
) и, возможно,include
заявление.Таким образом, общее сообщение состоит в том, что конструкции препроцессора позволяют вам создавать несколько различных разновидностей файлов MSI из одного источника WiX XML.
В вашем случае это даст один источник WiX XML и три MSI-файла - каждый для отдельной версии приложения. Все похожие, но только с необходимыми компонентами.
Запуск установки через
/i
или административный образ (извлечение файла) через/a
выдаст только те компоненты, которые вы добавили к этому варианту установки, но у вас, как вы говорите, нет ни одного MSI, а три разных в зависимости от того, как вы скомпилировали.Я предпочитаю использовать
?include?
операторы для включения файлов фрагментов WiX, а не просто для кондиционирования компонентов напрямую?if?
как вы упомянули. Ниже приведен пример разницы в разделе " Конструкции препроцессора ".
Функции MSI (как ответил PhilDW) : вы также можете положиться на функции MSI, чтобы обеспечить единую настройку в разных вариантах. Функции используются для разделения MSI на различные выбираемые пользователем элементы установки (некоторые из которых вы можете сделать обязательными).
- Функции позволяют устанавливать один MSI с различными вариантами, в то же время он содержит все компоненты, необходимые для каждого варианта. Компоненты кондиционирования могут достичь аналогичных эффектов.
- Компоненты кондиционирования напоминают манипуляции с функциями, но работают на более примитивном и фундаментальном уровне. Это не выбираемые пользователем установочные блоки, а фундаментальные и элементарные фрагменты вашего продукта, которые можно установить и скрыть от пользователя - в то время как функции выбираются пользователем и обычно видны для пользователя.
Какие функции должны быть установлены, могут быть изменены пользователем или программно с помощью настраиваемого действия (например, для автоматического изменения технических требований пользователя и принудительного применения технического проекта).
Управление функциями пользователя
Пользователи могут управлять функциями для установки в интерактивном режиме с помощью диалогового окна настройки FeatureTree, которое можно найти в большинстве установок (не во всех). Обычно для этого требуется выборочная установка.
Вы также можете указать, какие функции установить в настройке, используя командную строку, запускающую установку, используя свойство ADDLOCAL и свойство REMOVE (и, возможно, другие подобные свойства - подробности см. По ссылке).
Иногда вы можете установить пользовательское свойство во время установки, которое будет запускать набор стандартных функций для установки на основе указанного "издания", что подводит нас к следующему пункту.
Программное управление функциями
Добавление ссылки на ответ о программном элементе управления: Как установить функцию на основе свойства, заданного в настраиваемом действии?
Как уже говорилось, вы можете манипулировать функциями для установки через командную строку, используя свойство ADDLOCAL и свойство REMOVE внутри установки во время ее работы. Для этого вы можете использовать настраиваемое действие.
Существует также свойство INSTALLLEVEL, которое имеет отношение к состоянию установки компонентов. Для каждой функции существует уровень установки, и на него могут влиять условия, установленные в таблице Условий.
Таким образом, таблица Условий может использоваться для изменения состояния выбора любой записи в таблице объектов на основе условного выражения.
Другими словами, вы можете использовать это, чтобы установить функции для установки или не установки по умолчанию в зависимости от условия.
В дополнение к концепции INSTALLLEVEL вы также можете использовать настраиваемые действия для управления состоянием выбора функции.
- Сегодня это на удивление более надежно, чем состояние функциональности, поскольку многие упаковщики приложений обычно максимально используют свойство INSTALLLEVEL, чтобы принудительно установить все функции. Это неправильно, так как некоторые функции, возможно, не нужно устанавливать, если они несовместимы с ОС, на которой вы работаете. Я пытался донести это до многих глухих ушей.
Используя эти программные конструкции, ваша установка может, например, изменить состояние выбора функции для того, что должно быть установлено, на основе серийного ключа, введенного пользователем.
Ваша установка также может определить, что определенная функция не должна быть установлена в зависимости от операционной системы, которую вы используете (не устанавливайте
Tablet OS
особенности, например).Может быть любое количество технических и практических причин для программного изменения выбора функций.
Важно отметить, что общий результат заключается в том, что выбор функции может быть установлен с помощью командной строки или пользователем, а затем ваша настройка вносит некоторые изменения "по капотам" по техническим причинам.
И просто укажу на это: функции, которыми манипулируют для установки программно, как правило, скрыты от глаз (но все же возможно переопределить через командную строку - что может быть проблемой).
Подробнее о функциях, компонентах и настройке настроек для установки здесь: Как лучше использовать файлы MSI.
Средство запуска Setup.exe: "современный" способ выполнить сложное развертывание в разных вариантах может заключаться в использовании функции записи WiX для компиляции небольших установок MSI, которые устанавливаются в разных "наборах", чтобы получить другое состояние установки.
- Я считаю, что это слишком сложно для общего пользования, но это, безусловно, возможно. Я думаю, что некоторые находят это проще, поскольку меньше манипуляций с функциями. Может быть, мне просто не хватает опыта с этим.
- Преимущество заключается в том, что файлы MSI меньшего размера устанавливаются быстрее, и вы можете обновить один файл MSI и создать новую оболочку setup.exe, а затем выполнить полный контроль качества всего решения без перестройки всех настроек.
- В моем мире единственный обновленный MSI в любом случае требует полного контроля качества, поэтому я не всегда покупаю эти "аргументы простоты" самостоятельно. Каждый цикл выпуска имеет риски, и, следовательно, добавляет к общему риску. Тем не менее, может быть здорово иметь возможность перестроить крошечную установку и сохранить стабильную большую.
Практическое использование
Я предпочитаю делать как можно меньше вариантов настройки, но в большинстве случаев я использую препроцессорные конструкции для создания различных настроек для разных языковых версий (английский, немецкий, русский), а также для разных выпусков продукта (Enterprise, Professional, Standard)., Я обычно настраиваю их все, связанные с совместным использованием кода обновления, и не могу установить их параллельно.
Я чувствую, что один MSI получает больше ресурсов QA и, следовательно, будет лучше тестироваться. Тем не менее, этот единственный подход MSI обычно ломается, если настройки очень велики - в этом случае я хотел бы разделить их. Я также хотел бы сделать отдельные настройки для каждого языка по практическим и деловым причинам, объясненным здесь. Практические и юридические требования (лицензирование) также могут привести к необходимости компилировать специальные версии той же установки MSI. Меня также попросили создать новые версии MSI для производителей комплектного оборудования.
И теперь неожиданный вывод (который вы никогда не просили:-)): со всем этим сказано, что в идеальном мире мне нравится устанавливать все функции без каких-либо технических проблем в настройке, и использовать серийный ключ, чтобы определить, какие функции приложения и модули должны быть активированы в приложении. Мне также нравится помещать проверку серийного ключа в приложение, а не в настройку. Причина? Я хочу, чтобы настройки были как можно более примитивными, чтобы гарантировать правильную установку приложения без высокого процента ошибок развертывания. Поэтому я стремлюсь к сложности, которую нужно убить при развертывании, чтобы обеспечить меньше проблем с поддержкой развертывания. Надежное развертывание имеет решающее значение для успеха продукта. После установки ваше приложение может запускаться в гораздо более отлаживаемом и предсказуемом контексте (без проблем с условностями, олицетворением или последовательностью) и сообщать пользователю о любых ошибках в интерактивном и содержательном режиме - и они могут обращаться в службу поддержки с большей надеждой на успешное решение любых проблем. чем то, что было бы, если бы установка только что разбомбила с таинственным неинтерактивным сообщением об ошибке (в системном журнале событий).
После того, как вы получили хорошее и простое решение для развертывания, ваша работа в качестве менеджера релизов и разработчика по настройке должна быть расширена, чтобы позаботиться о последовательности запуска приложения, конфигурации файлов и общей конфигурации, а также о моих возможностях поддержки и отладки, которые вы, возможно, захотите добавить в приложение (самопроверка приложения и регистрация и автоматический сбор информации для отправки в службу поддержки). Попробуйте расширить свою ответственность и влияние на само приложение, чтобы развертывание было "как можно более примитивным". Все, что может быть закодировано в приложении, а не в настройке, будет более надежным в долгосрочной перспективе (и намного проще в отладке).
Вернемся к реальности: для реального развертывания вы получите кучу файлов с нерегулярной схемой управления версиями, которые будут доставлены вам через медленный сетевой ресурс с кучей непоследовательных инструкций от разработчика, который получает оффшор и получает почасовую оплату (вы можете быть уверены, что он чувствует боль тоже:-)). И у них будет куча частично безумных требований к вашей установке, чтобы творить чудеса, чтобы скрыть свой не идеальный дизайн (это все, что им платили за создание). Это не напыщенная речь, это реальность - грустно сказать (хорошо, это напыщенная речь). Мы должны улучшить общий дизайн приложения, чтобы развертывание было менее подвержено ошибкам. Волшебство действительно может быть сделано в настройке, но оно вызовет более высокий процент ошибок для развертывания из- за неизбежной и неуправляемой сложности развертывания (наиболее значительно: 1)
ошибки накапливаются - каждый выпуск добавляет риски и возможности нарушать работоспособность вашей установки (иногда вам нужно все вернуть назад и начать заново - с большими затратами), 2)
целевые системы находятся в крайне разных и непредсказуемых состояниях (любое состояние, любой язык, любое издание ОС, любое оборудование, любое вредоносное ПО и т. д.), 3)
Отладка очень трудна, когда у вас нет интерактивного доступа к проблемным системам - смотрите подробности в конце связанного ответа. И я добавлю 4th issue
Отказ от второго: можете ли вы гарантировать развертывание на машине, заполненной вредоносными программами? Такие системы невозможно поддерживать и отлаживать - просто сделайте выбор, чтобы найти критическую проблему, которую вы не можете исправить. Если ваш пакет не работает в таких вредоносных системах, это естественный процент ошибок, который неизбежен.
Общий смысл очевиден: мы не можем учесть эти неизвестные вещи - мусор внутри, мусор вне (с извинениями за то, как это звучит) - будет процент ошибок - каждый раз при развертывании - даже для идеальных пакетов. Обязательно соберите всех доступных и всегда ценных QA-ребят и научите их тестированию установки (тестирование всех режимов установки, тестирование удаления и взаимодействия с другими приложениями, тестирование реальных сценариев обновления, тестирование определенных расширенных функций установки, таких как проверка лицензии и т. Д.)....). Получите всю возможную помощь и оцените их вклад. Если не что иное, как сообщники:-). Серьезно: неспособность эффективно использовать имеющиеся QA-ресурсы и помочь обучить их тестированию развертывания - это мой главный вопрос, так как я больше всего пренебрегаю менеджером релизов и разработчиком настроек. Это безопасное предположение, что вы будете в долгу перед своими QA-парнями бутылкой Horílka - или зеленым чаем или чаем Rooibos - в зависимости от того, где вы находитесь в мире:-).
Конструкции препроцессора
Я бы вероятно использовал препроцессорные конструкции ?if?
а также ?include?
выборочно включать различные разделы исходного кода / разметки WiX XML на основе определенной вами версии в ?define?
утверждение в верхней части образца:
<?define EditionType = “LITE” ?>
<!-- You can put your edition-specific components in an include file -->
<?if $(var.EditionType) = "200" ?>
<?include "200Features.wxi" ?>
<?endif ?>
<?if $(var.EditionType) = "LITE" ?>
<?include "LiteFeatures.wxi" ?>
<?endif ?>
Вместо использования включаемых файлов, вы также можете сделать это встроенным в ваш основной источник (это может быть то, что вы сделали):
<?if $(var.EditionType) = "200" ?>
<Component>
<File Source="$(var.MenusPath)\ClientListView 200.r5m" />
</Component>
<?endif?>
<?if $(var.EditionType) = "LITE" ?>
<Component>
<File Source="$(var.MenusPath)\ClientListView Lite.r5m" />
</Component>
<?endif?>
Из вышеперечисленных вариантов я бы предпочел хранить компоненты, относящиеся к изданию, в отдельном включаемом файле (первый вариант) - тогда в исходном тексте WiX будет меньше "линейного шума" (меньше повторений конструкций препроцессора).
Включаемые файлы - это, по сути, просто XML-файлы WiX, которые, как и заголовочные файлы C++, включаются в родительский XML-файл WiX во время компиляции. Как сказал Фил, я бы использовал разные названия функций для разных изданий, поэтому вы определяете функцию 200Features
в 200Features.wxi включить файл, но вам не нужно использовать функции - хотя настоятельно рекомендуется.
Также следует помнить о концепции WiX элемента фрагмента. По сути, это способ перекрестной ссылки на контент в исходном файле WiX. Пример здесь.
Я должен упомянуть, что оригинальная концепция модулей слияния в MSI предоставляет другой способ обмена компонентами между различными установками, но мне больше нравится подход с использованием включаемых файлов. Модули слияния как-то похожи на объекты COM (двоичный блоб включен как версионное целое), тогда как включаемые файлы кажутся более динамичными в том смысле, что вы получаете последние файлы, связанные с каждой сборкой, без перестройки и контроля версий модулей слияния. Некоторые люди, несомненно, найдут это очень неправильно.
Ключ /a в командной строке msiexec не является установкой в обычном смысле. Это просто распаковка файлов в определенном месте. Если вам нужна реальная установка, вы должны использовать /i или просто дважды щелкнуть MSI-файл. Это даст вам правильную полную установку с помощью пункта "Программы и компоненты" и так далее.
Выбор того, что устанавливать, обычно выполняется путем разделения установки на функции, каждый из которых содержит набор компонентов, содержащих необходимые функции. В пользовательском интерфейсе WiX вы можете получить диалоговое окно для выбора функций, а режим обслуживания позволит вам вернуться и изменить их. При установке из командной строки вы просто скажете /i [msi file] ADDLOCAL=Feature1,Feature2 и так далее. Если вы действительно хотите использовать "аромат", то внутренне вы бы превратили его в список ADDLOCAL.
Спасибо за информацию, но я думаю, вы не поняли, чего я пытался достичь; Я не хочу запускать установщик через /i, потому что, как вы сказали, это фактически установит файлы, изменит реестр и т. Д. Я хотел запустить установщик дважды - один раз для flavor 200, затем снова для flav Lite; таким образом, я получу две папки с файлами, которые "будут" установлены, если я запустил его с /i. Очевидно, я не могу запустить его дважды с /i, потому что при втором запуске он удалит первый.
Во всяком случае, я обнаружил, что условия внутри компонентов игнорируются во время "установки" администратора, тогда как? Если? операторы не игнорируются - не уверен, почему это так, но теперь я удалил все свои операторы условия и заменил их на операторы IF - так что теперь я могу делать то, что хотел - запустить его дважды с / a, и каждая папка будет содержать файлы, уникальные для этого аромата.