Я новичок в программировании Windows, но мне нужно создать сложный установщик MSI, который устанавливает плагин с помощью набора инструментов WiX. Программа установки должна обнаруживать при запуске все установленные версии определенного программного обеспечения и их подключаемые модули через API реестра Windows. После этого все они должны отображаться на отдельной странице (диалоге) с соответствующими флажками. Пользователь должен выбрать, в какие версии он хочет установить плагин.

Я создал настраиваемое действие (на C ++ и поместило его в DLL, которая находится в базе данных MSI), которое взаимодействует с API реестра, затем перебирает результаты и добавляет временные записи в таблицы базы данных:

  • добавляет свойства пути для сохранения путей к плагинам;
  • добавляет записи в таблицу CheckBox;
  • добавляет свойства для удержания их состояний;
  • добавляет для них условия, затем проверяет состояние их свойств и включает / отключает их;
  • добавляет события для сброса свойств пути в соответствии со свойствами состояния.

Запускается после AppSearch

<InstallUISequence>
   <Custom Action="PopulateVersions" After="AppSearch">Not Installed</Custom>
</InstallUISequence>

Затем нажатие кнопки «Далее» (я знаю, что это неправильное место для таких вещей) выполняет настраиваемое действие, которое отфильтровывает активные пути свойств, берет первый из них и выполняет действие SetTargetPath (оно отлично работает). Для остальных из них действие вставляет соответствующие временные записи в:

  • таблица DuplicateFile, где DestFolder - имя свойства;
  • таблица Component, копирующая все значения полей из исходного компонента, устанавливая значение поля Component_Parent на исходное;
  • Таблица Справочника. Одна запись для каждого свойства пути, Direcory_Parent - TARGETDIR;

Он установил плагин только для первого пути к свойству, на который ссылается (который был передан в действие SetTargetPath).

Хорошо ... Я добавил несколько элементов CopyFile, которые относятся к моим настраиваемым свойствам (я объявил несколько свойств, чтобы предотвратить ошибку сборки MSI из-за неизвестных свойств) в разметку WiX только для тестирования:

    <Property Id="PathProperty0" Value="{}"/>
    <Property Id="PathProperty1" Value="{}"/>
    <Property Id="PathProperty2" Value="{}"/>

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFiles64Folder">
        <Directory Id="INSTALLLOCATION" Name="MyPluginDir">
          <Component Id="PluginExt" Guid="C112184A-307C-5E15-994F-0DFDA9DD427E">
            <File Id="MyPlugin" Name="MyPlugin.dll" Source="MyPlugin.dll" Vital="yes" />
            <CopyFile Id="MyPlugin_Copy1" FileId="MyPlugin" DestinationProperty="PathProperty1"/>
            <CopyFile Id="MyPlugin_Copy2" FileId="MyPlugin" DestinationProperty="PathProperty2"/>
          </Component>
        </Directory>
      </Directory>
    </Directory>

Теперь ProgressDialog сообщает, что "{}" - недопустимый путь, но все свойства были установлены на допустимые пути (я проверил это при отладке)! Похоже, что он забывает или игнорирует все временные изменения базы данных / изменения свойств после отображения запроса UAC повышения прав, который запрашивает доступ к тому же файлу MSI. Запрос появляется после нажатия кнопки «Установить» (со значком щита) . Возможно, он снова читает базу данных и не находит никаких изменений, поскольку они были в памяти или кеше, я не знаю.

Что я делаю не так или как правильно сделать этот установщик? ИМХО моя реализация слишком сложна. Мне нужна твоя помощь.

0
QBatman 25 Дек 2015 в 19:00

2 ответа

Лучший ответ

Я вижу как минимум две ошибки:

  1. Свойства для путей, которые вы хотите изменить во время выполнения, должны быть PUBLIC properties (то есть их имена не должны содержать строчные буквы. Кроме того, они, вероятно, должны быть перечислены в SecureCustomProperties, которое вы можете гарантировать, объявив их в своем источнике со значением или без него и указав Secure атрибут.

  2. Значение, которое вы указываете для своего свойства, связанного с каталогом, буквально {}. Это необычное значение, и оно редко бывает правильным. Обычно вместо этого требуется пустая строка. Исключение составляют случаи, когда вы находитесь в контексте Formatted и необходимо указать непустую строку, которая приводит к пустому строковому значению, например параметр свойства ControlEvent. Элемент Property вашего источника wix не является таким контекстом.

Я не уверен во всей сложности описанного вами подхода (я не смог полностью его продумать), но я хочу поддержать общий подход, который вы применяете для программного создания табличных данных и разрешения установщику Windows остальное сделай. Этот подход достаточно важен, чтобы дать ему своеобразное название: полу- настраиваемое действие.

В соответствии с инструкциями по полу-настраиваемым действиям вы, вероятно, захотите запланировать действие PopulateVersions как в InstallUISequence, так и в InstallExecuteSequence (особенно если он использует RemoveFile для выполнения очистки), чтобы гарантировать, что установка, обслуживание и автоматическое удаление получают надлежащие данные таблицы добавлены.

2
Michael Urman 26 Дек 2015 в 14:04

Я думаю, вы усложняете это. Вы можете просто создать функцию AddIns с кучей дополнительных функций AddInVersionXXXX и использовать результаты поиска приложений в условиях функции, а затем отобразить диалоговое окно Custom Setup.

В моем IsWiX я делаю то же самое, за исключением того, что всегда устанавливаю все обнаруженные версии. Хитрость в том, что CopyFile аккуратно пропустит копию, если свойство каталога не имеет значения. Это действительно просто и можно увидеть здесь:

http://iswix.codeplex.com/SourceControl/latest#main/Source/Installer/IsWiXNewAddInMM/IsWiXNewAddInMM.wxs

2
Christopher Painter 26 Дек 2015 в 22:33