Pergunta

Estou tentando criar um projeto de configuração usando Wix Isso me permitirá instalar vários recursos de um único produto. Como posso atualizar um dos recursos instalados (que é independente dos outros recursos instalados) sem precisar reinstalar os outros recursos na árvore de recursos?

Por exemplo, eu quero poder ter um projeto (voltando para Hellowolrd) chamado Hellowolrd, que (surpresa) imprime "Hello World!" na tela. Digamos que eu tenho três dessas aplicações do Hello World, Hello World 1, Hello World 2 e Hello World 3. Cada uma das quais impressões na tela Hello World 1, 2 ou 3, respeitosamente. O que eu gostaria é criar um MSI que, por padrão, instale todos os três "recursos", mas também permite a atualização de cada recurso individualmente em um horário posterior.

Aqui está o meu layout da minha solução:

Solution Explorer http://img12.imageshack.us/img12/5671/solutionExplorerm.jpg

Meu arquivo wix product.wxs se parece com o seguinte:

<?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="Software\HelloWorldInstaller\HelloWorld1\Install" 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="Software\HelloWorldInstaller\HelloWorld2\Install" 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="Software\HelloWorldInstaller\HelloWorld3\Install" 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>

Agora, quando isso é construído, ele instala os recursos como seria de esperar. No entanto, quando você faz uma modificação para o helloworld1.vb e o recompile, eu gostaria que ele fosse capaz de reinstalar (atualizar) apenas esse recurso, não todos eles.

Quando atualizo um arquivo e reconstruo a solução e tento instalar o MSI, recebo este erro:

Erro MSI http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg

Atualizei meu código para permitir a desinstalação dos recursos e permitir o uso de códigos de atualização, mas isso não instalei todos os recursos e reinstalei todos eles.


-Aplicação do mundo real-

O aplicativo do mundo real para isso é um grande pacote de software que precisa de vários aplicativos de suporte que executam como serviços/tarefas programadas regularmente. Gostaria de obter a instalação desses aplicativos de suporte em um MSI, permitindo que não tenhamos um pesadelo de lançar cada exe individualmente. Sei que, se tivermos uma atualização para um dos exe, poderíamos compilar manualmente esse exe e lançá -lo, mas eu gostaria de fazer isso de uma maneira completamente reproduzível.

Qualquer ajuda seria apreciada,

Obrigada!

EDITAR:

Eu adicionei a fonte para download de Código do Google. Obrigado novamente!

Foi útil?

Solução

Eu descobri isso e pensei em publicar a resposta aqui para referência futura para os outros. Por isso, expliquei totalmente o problema, vou aprofundar o cenário do mundo real.

Temos um software moderadamente grande que exige que tenhamos vários aplicativos de suporte executados em vários servidores diferentes. Nossa progressão atual de atualizações torna moderadamente difícil atualizar o código de maneira confiável. Atualmente, usamos o Exe de extração de auto -extração para lançar nosso código para os diferentes servidores. O problema surge quando temos um número tão grande de aplicativos de suporte que fica difícil garantir que os aplicativos foram instalados corretamente com as configurações corretas, etc. Para resolver esse problema que estamos procurando na capacidade de, em vez de comprimir cada um de cada um de Os aplicativos de suporte, criamos um único instalador (MSI) que permitirá à equipe de infraestrutura instalar um conjunto específico de aplicativos de suporte a cada máquina em determinada. Quando tivermos uma grande mudança (por exemplo, de 1,0 a 2.0), faremos uma instalação completa de atualização (o que significa que todos os serviços/processos precisarão ser interrompidos, não instalados, instalados e iniciados.) Quando tivermos uma pequena mudança, Gostaríamos de apenas parar e reinstalar os serviços/processos afetados, sem tocar em outros aplicativos. Agora, chega de mim divagando, vamos para a solução:

Modifiquei o produto wix.wxs para remover os atalhos, pois realmente não precisamos deles em nosso cenário. Aqui está o arquivo WXS atualizado:

<?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>

Agora, junto com isso, para nossas atualizações menores, procuraremos lançar patches para nossos componentes.

Por exemplo, digamos que temos um produto, que possui três componentes - 1,2 e 3. Esses três componentes devem ser executados como serviços ou tarefas programadas. A natureza do nosso produto, não podemos desligar todos os nossos serviços para atualizar ou corrigir um de nossos componentes. Portanto, se depois de instalarmos a versão 1.0, encontramos um bug no componente 2, mas não queremos que 1 ou 3 seja afetado pela correção que está sendo aplicada a esse bug, lançaremos um patch para o componente 2, Assim, apenas o componente 2 será afetado.

Para o nosso exemplo rápido acima, estamos usando o Helloworld1, Helloworld2 e HelloWorld3 como nossos 3 componentes em nosso aplicativo de software. O pensamento é que devemos ser capazes de instalar todos os três com um MSI, mas atualizar cada um de forma independente sem que ele afete nenhum dos outros componentes instalados.

Então, para demonstrar isso, criei os três aplicativos de console acima que exibirão "Hello World 1!", "Hello World 2!" E "Hello World 3!". Depois de lançar o MSI inicial, digamos que encontramos um "bug" que exige que tenhamos o helloworld1 "Olá, World 1! Atualizado". em vez de. Aqui está o que faremos para simular isso:

  1. Crie o produto.wixobj executando este comando no prompt de comando:
    candle.exe Product.wxs
    Lembre -se de que, para ligar para o Candle.exe ou qualquer um dos comandos WIX, o diretório de instalação do WIX deve estar na sua variável de caminho. (Tutorial curto sobre a atualização da variável do ambiente do caminho) Além disso, execute os comandos no mesmo diretório que o seu arquivo. WXS.
  2. Crie a primeira versão do seu produto (digamos 1.0):
    light.exe Product.wixobj -out ProductA-1.0.msi
  3. Agora encontre um bug (altere a saída do helloworld1 para dizer "Olá, World 1! Atualizado".) Então, então Atualize a versão de montagem e a versão do arquivo. Isso é importante, pois é assim que o Wix pode dizer que os exe são diferentes.
  4. Execute o mesmo comando que a etapa um (para uma boa medida):
    candle.exe Product.wxs
  5. Execute quase o mesmo comando que a etapa dois:
    light.exe Product.wixobj -out ProductA-1.1.msi
    Observe que esta é a versão 1.1 em vez de 1.0 (este é o MSI com nosso código atualizado). No entanto, não queremos apenas instalar isso, continue lendo.
  6. Aqui está a parte divertida, obtemos a diferença nos dois MSIs com o seguinte comando:
    torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
  7. Agora, criamos o arquivo de patch a partir deste (patch.wxs será explicado abaixo):
    candle.exe Patch.wxs
  8. Agora criaremos o arquivo wixmsp com este comando:
    light.exe Patch.wixobj -out Patch.WixMsp
  9. E agora, a parte divertida. Crie o arquivo MSP com este comando:
    pyro.exe Patch.WixMsp -out Patch.msp -t RTM Diff.Wixmst

Agora, se tudo correr conforme o planejado, você deve ter dois arquivo MSI e um MSP. Se você instalar o primeiro MSI (Productha-1.0.msi) e executar o Helloworld1.exe, você deve ver a mensagem "Olá World 1!". Apenas por diversão (e exemplo), execute os outros aplicativos e deixe -os em execução (eu construí uma parada para mantê -los abertos). Fechar Helloworld1.exe Como agora vamos aplicar a atualização para esse exe, mas, ao fazê -lo, não afetaremos o Helloworld2.exe ou o Helloworld3.exe. Se você agora instala o arquivo msp (patch.msp) e execute o helloworld1.exe, verá a mensagem atualizada: "Hello World 1! Atualizado".

Agora, para o mágico Arquivo Patch.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>

Não parece muito, não é? Bem, as partes mais interessantes são estas:

  1. <PatchBaseline Id="RTM"/> - Se você se lembra, se você se lembra, é usado em nossa criação do patch msi. O "RTM" é referido na última etapa acima: -t RTM - Eles têm que combinar.
  2. <ComponentRef Id="HelloWorld1Component"/> - Isso aponta o patch para o componente correto a ser atualizado, no nosso caso, helloworld1Component.

Se você está pesquisando, o código acima pode parecer familiar porque veio de Blog de Peter Marcu: Wix: Construindo um patch usando o novo sistema de construção de patches - Parte 3

Eu também confiei muito em Blog de Alex Shevchuk: De MSI a Wix, Parte 8 - Atualização Principal

Se você está se perguntando: "Uau, são muitas etapas, por que alguém daria tantos passos?", Lembra -se de que, quando o trabalho duro (acima) terminar, você precisa mover isso para sua rotina de integração. Isso é certo, integrar, integrar, integrar! Como você faz isso? Bem, isso é um pouco mais de pesquisa e talvez um post no blog? - Provavelmente. Para tirá -lo do pé direito, aqui está um artigo incrível sobre Automatize versões com o MSBuild e o Windows Installer XML.

Uau, espero que você leia tudo isso (os dois) e aprendeu muito. Espero que isso ajude alguém que não seja eu.

Obrigada!

Outras dicas

Parece que você descobriu o cenário de atualização, agora você só precisa descobrir Onde colocar RemoverexistingProducts em uma grande atualização do MSI Portanto, que os recursos não são reinstalados se não mudarem :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top