Может ли файл .msi установиться самостоятельно (предположительно с помощью специального действия)?
-
01-07-2019 - |
Вопрос
Я хочу создать MSI, который в процессе установки будет развертываться вместе с содержащимися в нем файлами/компонентами в TargetDir.
Таким образом, MyApp.msi содержит MyApp.exe и MyAppBootstrapperEmpty.exe (без ресурсов) в своей таблице файлов.
Пользователь запускает MyAppBootstrapperPackaged.exe (содержащий MyApp.msi в качестве ресурса, полученного где-то из Интернета, по электронной почте или иным образом).MyAppBootStrapperPackaged.exe извлекает MyApp.msi во временную папку и запускает его через msiexec.exe.
После завершения процесса msiexec.exe мне нужны MyApp.msi, MyBootstrapperEmpty.exe (И MyApp.exe в папке %ProgramFiles%\MyApp, чтобы MyApp.exe мог иметь гарантированный доступ к MyApp.msi при его запуске (для создания приведенного ниже файла) упомянутый упакованный контент).
MyAppBootstrapper*.exe может попытаться скопировать MyApp.msi в папку %ProgramFiles%\MyApp, но для этого потребуется повышение прав, и он не позволит удалить его с помощью процесса удаления установщика Windows (из пункта «Установка и удаление программ» или иным образом), что должно быть сохранено.
Очевидно (я думаю, это очевидно - я ошибаюсь?) Я не могу включить MSI в качестве файла в свой Media/CAB (сценарий с курицей и яйцом), поэтому я считаю, что это нужно будет сделать с помощью специального действия перед установкой. процесс, добавляя исходный MSI в Media/CAB базы данных MSI и соответствующую запись в таблице файлов на лету.Можно ли это сделать и если да, то как?
Подумайте о модели распространения контента, в которой файлы контента должны распространяться только вместе с Приложением.Контент создается конечным пользователем через Приложение во время выполнения и упаковывается в распространяемый EXE-файл, который включает в себя как Приложение, так и контент.
Установщик MyApp должен оставаться в формате MSI, но может запускаться с помощью EXE-файла Bootstrapper.Установленный MyApp.exe должен иметь доступ как к MyApp.msi, так и к EXE. Приложение должно «собирать» во время выполнения из базового (пустого) MyAppBootstrapper.exe, который также устанавливается MSI, и содержимого, созданного конечный пользователь.Ресурс MSI EXE-файла должен быть таким же, как тот, который использовался для установки приложения, которое выполняет упаковку во время выполнения.
WIX не следует устанавливать вместе с MyApp.
Не может быть никаких сетевых зависимостей во время выполнения/упаковки (т.невозможно выполнить упаковку через веб-сервис — необходимо выполнить локально).
Я знаком (и использую) настраиваемые действия (управляемые и неуправляемые, через DTF и т. д.).
Решение
Добавьте несжатый носитель в ваш wxs следующим образом:
<Media Id='2'/>
А затем создайте компонент с элементом File следующим образом:
<File Source='/path/to/myinstaller.msi' Compressed='no' DiskId='2' />
Это заставит установщик искать файл с именем «myinstaller.msi» на установочном носителе в той же папке, что и устанавливаемый MSI.Приведенный выше исходный путь должен указывать на фиктивный файл, он нужен только для того, чтобы успокоить Wix.
Редактировать:Следующий пример test.wxs демонстрирует, что это работает.Он создает файл test.msi, который устанавливается в папку c:\program files est.Обратите внимание, что вам нужно поместить фиктивный файл test.msi в ту же папку, что и text.wxs, чтобы успокоить Wix.
<?xml version='1.0' encoding='utf-8'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product
Name='ProductName'
Id='*'
Language='1033'
Version='0.0.1'
Manufacturer='ManufacturerName' >
<Package
Keywords='Installer'
Description='Installer which installs itself'
Manufacturer='ManufactererName'
InstallerVersion='100'
Languages='1033'
Compressed='yes'
SummaryCodepage='1252'/>
<Media Id='1' Cabinet='test.cab' EmbedCab='yes'/>
<Media Id='2' />
<Directory Id='TARGETDIR' Name="SourceDir">
<Directory Id='ProgramFilesFolder'>
<Directory Id='TestFolder' Name='Test' >
<Component Id="InstallMyself">
<File Source="./test.msi" Compressed="no" DiskId="2" />
</Component>
</Directory>
</Directory>
</Directory>
<Feature
Id='Complete'
Display='expand'
Level='1'
Title='Copy msi file to program files folder'
Description='Test'>
<ComponentRef Id="InstallMyself" />
</Feature>
</Product>
</Wix>
Другие советы
Запуск одного пакета .MSI «изнутри» другого пакета .MSI называется вложенная установка, И его плохое джуджу (см. Правило 20).Установщик Windows имеет некоторые глобальные данные, которые он использует для управления текущей установкой, и он плохо справляется с несколькими установками одновременно.По той же причине, если вы запустите одну установку, а затем попытаетесь запустить другую, пока первая еще выполняется, вы обычно увидите всплывающее окно с сообщением «идет еще одна установка, подождите, пока она не завершится».
У вас может быть программа, обычно называемая загрузчиком (думаю, вы имеете в виду именно это), которая сама по себе не является установочным пакетом, но содержит установочный пакет (например, .MSI или .EXE) в качестве ресурса, возможно, в сжатом виде.Действие программы-загрузчика заключается в извлечении/расширении ресурса в файл, обычно в виде файла. %TEMP%
каталог, затем либо запустите извлеченный .EXE, либо запустите MSIEXEC для извлеченного .MSI.Загрузчик может содержать несколько ресурсов и извлекать и устанавливать их один за другим, если вам нужно установить необходимые компоненты перед основным пакетом.Или вы можете отправить несколько пакетов в виде отдельных файлов и позволить загрузчику выполнить/установить их непосредственно с дистрибутивного носителя один за другим, или скопировать их на целевой компьютер и запустить серию установок оттуда, или...
Сам WiX не устанавливается, нет.Это инструмент, с помощью которого можно создавать пакеты .MSI.В списке пожеланий проекта WiX есть универсальная программа-загрузчик, но она еще не реализована.Доступны и другие загрузчики, например. Вот этот.
Вам не понадобится специальное действие — фактически, поскольку загрузчик сам по себе не является установочным пакетом установщика Windows, «настраиваемое действие» не имеет для него никакого значения.И если вы достаточно знакомы с центрами сертификации, чтобы знать об управляемых/неуправляемых/DTF, то вы знаете достаточно, чтобы избегать настраиваемых действий, когда это возможно.(ухмылка)
Я думаю, что вашему загрузчику гораздо проще извлечь файл MSI в какое-то заранее определенное место, а не во временную папку.Например, в C:\Documents and Settings\All Users\Application Data\My Company\My Product Install Cache.После завершения установки загрузчик оставит файл MSI там.Если на каком-то этапе пользователь решит переустановить ваш продукт, установщик Windows сможет найти исходный файл MSI.
Также добавьте путь к этому файлу в Таблица удаления файлов чтобы он удалялся при удалении.Вы можете использовать Элемент RemoveFile в WiX для этого.
Итак, если я понимаю, то я думаю, что мне нужно, чтобы приложение создало преобразование (MST), содержащее файлы содержимого, и применило его к базовому MSI.Хотя я до сих пор не уверен, что понимаю.:)
Я бы настроил путь к кэшу MSI в известное место.
Затем во время выполнения, если вам нужно «отредактировать» MSI, используйте VBScript или аналогичный.
Но все же я спрашиваю ПОЧЕМУ!?!
Я также работаю над способом развертывания нескольких файлов MSI.У меня есть программа bootstrapper.exe, которая объединяет файлы MSI и запускает их по одному.Это решает мою проблему в большинстве случаев.
Случай, который он не решает, — это распространение установки GPO (объект глобальной политики).Для запуска установки GPO требуется файл dot-msi.
Для этого я сделал вот что, что почти решило проблему (но не совсем).Я помещаю файлы dot-msi в таблицу файлов установщика, помещаю свой загрузчик в двоичную таблицу и запускаю его из специального действия, вставленного после InstallFinalize в InstallExecuteSequence.Конечно, загрузчик не сможет запускать другие MSI, поскольку MSI верхнего уровня содержит мьютекс _MSIExecute.
Пройти немного дальше было довольно легко.Я заставил загрузчик вернуть управление установщику верхнего уровня и продолжить.Затем я добавил вызов WaitForSingleObject, чтобы дождаться завершения установки верхнего уровня, после чего загрузчик сможет продолжить завершение установки.
Моя проблема заключается в том, что установка объекта групповой политики происходит во время загрузки, а установка верхнего уровня завершается до завершения работы дополнительных установщиков, и объект групповой политики перезагружает компьютер.
Установка верхнего уровня также возвращает статус успеха, если в дальнейшем установка может фактически завершиться неудачей.
Я все еще ищу способ заблокировать завершение установки верхнего уровня до тех пор, пока не завершится загрузчик.