Обновление отдельных функций в дереве функций WIX без удаления / обновления других функций)

Я пытаюсь создать проект установки с помощью WIX Это позволит мне установить несколько компонентов одного продукта. Как я могу обновить одну из установленных функций (которая не зависит от других установленных функций) без переустановки других функций в дереве функций?

например, я хочу иметь проект (возвращаясь в HelloWolrd) под названием HelloWolrd, который (сюрприз) печатает "Hello world!"на экране. Допустим, я имейте три из этих приложений hello world, Hello World 1, Hello World 2 и Hello World 3. Каждый из которых печатает на экране Hello World 1, 2 или 3, С уважением. Я хотел бы создать MSI, который по умолчанию устанавливает все три из этих "функций", но также позволяет обновлять каждую функцию отдельно в более позднее время.

вот мой макет моего решения:

Обозреватель Решений http://img12.imageshack.us/img12/5671/solutionexplorerm.jpg

мой продукт WIX.файл wxs выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="ca484210-c719-4b2e-b960-45212d407c11" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0" Manufacturer="HelloWorldInstaller" UpgradeCode="68eeb8cb-9ef3-443c-870c-9b406129f7ff">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <!-- Create Directory Structure -->
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="Hello World" />
            </Directory>
            <Directory Id="DesktopFolder" Name="Desktop"/>
        </Directory>

        <DirectoryRef Id="INSTALLLOCATION">
            <Component Id="HelloWorld1" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
                <RegistryKey Root="HKCU" Key="SoftwareHelloWorldInstallerHelloWorld1Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld1.exe" Name="$(var.HelloWorld1.TargetFileName)" Source="$(var.HelloWorld1.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld1ApplicationDesktopShortcut" Name="Hello World 1" Description="Hello World Application 1" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>

            </Component>
            <Component Id="HelloWorld2" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
                <RegistryKey Root="HKCU" Key="SoftwareHelloWorldInstallerHelloWorld2Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld2.exe" Name="$(var.HelloWorld2.TargetFileName)" Source="$(var.HelloWorld2.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld2ApplicationDesktopShortcut" Name="Hello World 2" Description="Hello World Application 2" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
            <Component Id="HelloWorld3" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
                <RegistryKey Root="HKCU" Key="SoftwareHelloWorldInstallerHelloWorld3Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld3.exe" Name="$(var.HelloWorld3.TargetFileName)" Source="$(var.HelloWorld3.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld3ApplicationDesktopShortcut" Name="Hello World 3" Description="Hello World Application 3" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
        </DirectoryRef>

        <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
            <ComponentRef Id="HelloWorld1"/>
        </Feature>
        <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
            <ComponentRef Id="HelloWorld2"/>
        </Feature>
        <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
            <ComponentRef Id="HelloWorld3"/>
        </Feature>

    </Product>
</Wix>

теперь, когда это построено, он устанавливает функции, как и следовало ожидать. Однако, когда вы вносите изменения в HelloWorld1.vb и перекомпилировать, я хотел бы, чтобы он мог переустановить (обновить) только эту функцию, а не все из них.

когда я обновляю один файл и перестраиваю решение, а затем пытаюсь установить msi, я получаю это ошибка:

ошибка MSI http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg

я обновил свой код, чтобы разрешить удаление функций и разрешить использование кодов обновления, но это не установило все функции и переустановило их все.


-- реальное применение мира --

реальное приложение к этому-большой программный пакет, который нуждается в нескольких приложениях поддержки, которые работают как услуги / запланированные задачи на регулярной основе. Я хотел бы получить установку этих поддерживающих приложений в один MSI, что позволяет нам не иметь такого кошмара развертывания каждого exe индивидуально. Я знаю, что если у нас есть обновление для одного из exe, мы могли бы просто вручную скомпилировать этот exe и развернуть его, но я хотел бы сделать это полностью воспроизводимым образом.

любая помощь будет appriciated,

спасибо!

изменить:

I добавлен источник для загрузки из Код Google. Еще раз спасибо!

2 ответов


я понял это и подумал, что я опубликую ответ здесь для дальнейшего использования для других. Итак, я полностью объяснил проблему, я войду в более глубокий сценарий реального мира.

у нас есть умеренно большой кусок программного обеспечения, который требует от нас иметь несколько вспомогательных приложений, которые работают на нескольких разных серверах. Наша текущая прогрессия обновлений делает его умеренно сложным для обновления кода надежным способом. В настоящее время мы применяем извлечение exe для развертывания нашего кода на разных серверах. Проблема возникает, когда у нас есть такое большое количество поддерживающих приложений, что становится трудно убедиться, что приложения установлены правильно с правильными настройками конфигурации и т. д. Чтобы решить эту проблему, мы изучаем возможность вместо сжатия каждого из поддерживающих приложений, мы создаем один установщик (MSI), который позволит команде инфраструктуры установить определенный набор поддержка приложений для каждой конкретной машины. Когда у нас есть серьезные изменения (например, от 1.0 до 2.0), мы сделаем полную установку обновления (то есть все службы/процессы должны быть остановлены, не установлены, установлены и запущены.) Когда у нас есть незначительные изменения, мы хотели бы только остановить и переустановить затронутые службы/процессы, не касаясь других приложений. Теперь, хватит меня бессвязно, давайте доберемся до решение:

Я изменил WIX Товар.wxs для удаления ярлыков, поскольку они нам действительно не нужны в нашем сценарии. Вот обновленный файл wxs:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Product Id="13C373D3-5C27-487e-A020-C2C89E4607B1" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0"
      Manufacturer="HelloWorldInstaller" UpgradeCode="E7CB3C76-4D51-48a8-BFB4-6D11B2E2E65B">

  <Package InstallerVersion="200" Compressed="yes" />

  <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
  <FeatureRef Id="HelloWorld1Feature" />
  <FeatureRef Id="HelloWorld2Feature" />
  <FeatureRef Id="HelloWorld3Feature" />
 </Product>

 <Fragment>
  <Directory Id="TARGETDIR" Name="SourceDir">
   <Directory Id="ProgramFilesFolder">
    <Directory Id="INSTALLLOCATION" Name="Hello World" />
   </Directory>
   <Directory Id="DesktopFolder" Name="Desktop"/>
  </Directory>
 </Fragment>

 <Fragment>
  <DirectoryRef Id="INSTALLLOCATION">
   <Directory Id="HelloWorld1Directory" Name="Hello World 1">
    <Component Id="HelloWorld1Component" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
     <File Id="HelloWorld1.exe" Name="HelloWorld1.exe" Source="HelloWorld1.exe" DiskId="1" Checksum="yes" />    
    </Component>
   </Directory>
   <Directory Id="HelloWorld2Directory" Name="Hello World 2">
    <Component Id="HelloWorld2Component" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
     <File Id="HelloWorld2.exe" Name="HelloWorld2.exe" Source="HelloWorld2.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
   <Directory Id="HelloWorld3Directory" Name="Hello World 3">
    <Component Id="HelloWorld3Component" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
     <File Id="HelloWorld3.exe" Name="HelloWorld3.exe" Source="HelloWorld3.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
  </DirectoryRef>
 </Fragment>

 <Fragment>
  <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
   <ComponentRef Id="HelloWorld1Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
   <ComponentRef Id="HelloWorld2Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
   <ComponentRef Id="HelloWorld3Component"/>
  </Feature>
 </Fragment>
</Wix>

теперь вместе с этим, для наших незначительных обновлений, мы будем смотреть на выпуск патчей для наших компонентов.

например, предположим, у нас есть продукт, который имеет три компонента-1,2 и 3. Эти три компонента должны выполняться либо как службы, либо как запланированные задачи. Природа нашего продукта, мы не можем закрыть все наши услуги обновите или исправьте один из наших компонентов. Итак, если после установки версии 1.0 мы обнаружим ошибку в компоненте 2, но мы не хотим, чтобы 1 или 3 были затронуты исправлением, применяемым к этой ошибке, мы выпустим патч для компонента 2, таким образом, будет затронут только компонент 2.

для нашего быстрого примера выше мы используем HelloWorld1, HelloWorld2 и HelloWorld3 в качестве наших 3 компонентов в нашем программном приложении. Мысль в том, что мы должны быть в состоянии установить все три с одним MSI, но затем обновите каждый из них независимо, не затрагивая ни один из других установленных компонентов.

Итак, чтобы продемонстрировать это, я создал три консольных приложения выше, которые будут отображать " Hello World 1!", "Hello World 2!", и " Hello World 3!". Затем, после того, как мы выпустим первоначальный MSI, скажем, мы найдем "ошибку", которая требует от нас, чтобы HelloWorld1 сказал "Hello World 1! Усовершенствованный." вместо. Вот что мы сделаем, чтобы смоделировать это:

  1. создать продукт.wixobj, выполнив эту команду в командной строке:
    candle.exe Product.wxs
    пожалуйста, помните, что для того, чтобы вызвать свечу.exe или любая из команд WIX, каталог установки Wix должен быть в вашей переменной PATH. (Краткий учебник по обновлению переменной среды PATH) кроме того, выполните команды в том же каталоге, что и ваш продукт.файл wxs.
  2. создайте первую версию своего продукта (скажем, 1.0):
    light.exe Product.wixobj -out ProductA-1.0.msi
  3. теперь найдите ошибку (измените вывод HelloWorld1, чтобы сказать " Hello World 1! Усовершенствованный.") тогда обновите версию сборки и версию файла. Это важно, поскольку именно так WIX может сказать, что exe отличаются.
  4. выполните ту же команду, что и Шаг первый (для хорошей меры):
    candle.exe Product.wxs
  5. выполните почти ту же команду, что и второй шаг:
    light.exe Product.wixobj -out ProductA-1.1.msi
    обратите внимание, что это версия 1.1, а не 1.0 (это msi с нашим обновленным кодом). Однако мы не хотим просто установить это,продолжайте читать.
  6. вот забавная часть, мы получаем разницу в двух MSIs со следующей командой:
    torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
  7. теперь мы создаем файл патча из этого (Patch.wxs будет объяснено ниже):
    candle.exe Patch.wxs
  8. теперь мы создадим файл WixMsp с помощью этой команды:
    light.exe Patch.wixobj -out Patch.WixMsp
  9. а теперь, самое интересное. Создание MSP-файла с этой командой:
    pyro.exe Patch.WixMsp -out Patch.msp -t RTM Diff.Wixmst

теперь, если все прошло по плану, у вас должно быть два файла msi и один msp. При установке первого msi (ProductA-1.0.MSI) и запустить программу "helloworld1".exe, вы должны увидеть сообщение: "Hello World 1!". Просто для удовольствия (и пример), запустите оба других приложения и оставьте их работать (я встроил остановку, чтобы держать их открытыми). Закрыть Программу "Helloworld1".exe как мы теперь будем применять обновления, exe, но при этом мы будем не влияет на HelloWorld2.exe или HelloWorld3.исполняемый. Если вы теперь установите msp (патч.msp) файл, а затем запустите HelloWorld1.exe, вы увидите обновленное сообщение " Hello World 1! Усовершенствованный."

теперь волшебный патч.файл wxs:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Patch
   AllowRemoval="yes"
   Manufacturer="Dynamo Corp"
   MoreInfoURL="http://www.dynamocorp.com/"
   DisplayName="Sample Patch"
   Description="Small Update Patch"
   Classification="Update"
        >

  <Media Id="5000" Cabinet="RTM.cab">
   <PatchBaseline Id="RTM"/>
  </Media>

  <PatchFamilyRef Id="SamplePatchFamily"/>
 </Patch>

 <Fragment>
  <PatchFamily Id='SamplePatchFamily' Version='1.0.0' Supersede='yes'>
   <ComponentRef Id="HelloWorld1Component"/>
  </PatchFamily>
 </Fragment>
</Wix>

не похоже на много, не так ли? Ну а самые интересные части таковы:--14-->

  1. <PatchBaseline Id="RTM"/> - это, если вы помните, используется в нашем создании патча msi. "RTM" упоминается в последнем шаге выше:-t RTM - они должны совпадать.
  2. <ComponentRef Id="HelloWorld1Component"/> - это указывает патч на правильный компонент для обновления, в нашем случае HelloWorld1Component.

если вы занимались поиском вокруг, приведенный выше код может показаться знакомым, потому что он пришел из блог Питера Марку: WiX: создание патча с использованием новой системы Patch Building-Часть 3

я полагался на Алексея Шевчука Блог: от MSI до WiX, Часть 8-основное обновление

Если вам интересно: "Вау, это много шагов, зачем кому-то делать столько шагов?", пожалуйста, помните, что как только тяжелая работа (выше) будет сделана, вам нужно переместить это в свою интеграционную рутину. Право thats, интегрировать, интегрировать, интеграция! Как ты это делаешь? Ну, это немного больше исследований, и может быть в блоге? - Наверное. Чтобы получить вас на правой ноге, вот удивительная статья на автоматизация выпусков с MSBuild и Windows Installer XML.

Вау, я надеюсь, что вы прочитали все это (все вы), и многому научился. Надеюсь, это поможет кому-то, кроме меня.

спасибо!


звучит так, как будто вы выяснили сценарий обновления, теперь вам просто нужно выяснить где разместить RemoveExistingProducts в главном обновлении MSI чтобы функции не переустанавливались, если они не изменились:)