我们已经使用WiX有一段时间了,尽管人们对它的易用性有一些抱怨,但它运行得相当不错。我想要的是有用的建议:

设置WiX项目(布局、引用、文件模式) 将WiX集成到解决方案中,并构建/发布流程 为新的安装和升级配置安装程序 任何你想分享的好的WiX技巧


当前回答

为COM互操作注册。net程序集,兼容x86/x64

注意:这个片段本质上与REGASM Assembly.dll /codebase相同

在这个示例中发生了一些事情,所以这里是代码,我将在后面解释它……

  <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?include $(sys.CURRENTDIR)\Config.wxi?>
  <?if $(var.Win64) ?>
  <?define CLSIDRoots = "CLSID;Wow6432Node\CLSID"?>
  <?else ?>
  <?define CLSIDRoots = "CLSID"?>
  <?endif?>
  <!-- ASCOM Driver Assembly with related COM registrations -->
  <Fragment>
    <DirectoryRef Id="INSTALLLOCATION" />
  </Fragment>
  <Fragment>
    <ComponentGroup Id="cgAscomDriver">
      <Component Id="cmpAscomDriver" Directory="INSTALLLOCATION" Guid="{0267031F-991D-4D88-A748-00EC6604171E}">
        <File Id="filDriverAssembly" Source="$(var.TiGra.Astronomy.AWRDriveSystem.TargetPath)" KeyPath="yes" Vital="yes" Assembly=".net" AssemblyApplication="filDriverAssembly"  />
        <RegistryKey Root="HKCR" Key="$(var.DriverId)"  Action="createAndRemoveOnUninstall">
          <RegistryValue Type="string" Value="$(var.DriverTypeName)"/>
          <RegistryKey Key="CLSID">
            <RegistryValue Type="string" Value="$(var.DriverGuid)" />
          </RegistryKey>
        </RegistryKey>
        <?foreach CLSID in $(var.CLSIDRoots) ?>
        <RegistryKey Root="HKCR" Key="$(var.CLSID)" Action="none">
          <RegistryKey Key="$(var.DriverGuid)" Action="createAndRemoveOnUninstall">
            <RegistryValue Type="string" Value="$(var.DriverTypeName)"/>
            <RegistryKey Key="InprocServer32">
              <RegistryValue Type="string" Value="mscoree.dll" />
              <RegistryValue Type="string" Name="ThreadingModel" Value="Both"/>
              <RegistryValue Type="string" Name="Class" Value="$(var.DriverTypeName)"/>
              <RegistryValue Type="string" Name="Assembly" Value="!(bind.assemblyFullname.filDriverAssembly)" />
              <RegistryValue Type="string" Name="RuntimeVersion" Value="v2.0.50727"/>
              <RegistryValue Type="string" Name="CodeBase" Value="file:///[#filDriverAssembly]" />
              <RegistryKey Key="!(bind.fileVersion.filDriverAssembly)" >
                <RegistryValue Type="string" Name="Class" Value="$(var.DriverTypeName)"/>
                <RegistryValue Type="string" Name="Assembly" Value="!(bind.assemblyFullname.filDriverAssembly)" />
                <RegistryValue Type="string" Name="RuntimeVersion" Value="v2.0.50727"/>
                <RegistryValue Type="string" Name="CodeBase" Value="file:///[#filDriverAssembly]" />
              </RegistryKey>
            </RegistryKey>
            <RegistryKey Key="ProgId" Action="createAndRemoveOnUninstall">
              <RegistryValue Type="string" Value="$(var.DriverId)" />
            </RegistryKey>
            <RegistryKey Key="Implemented Categories" Action="createAndRemoveOnUninstall" >
              <RegistryKey Key="{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Action="createAndRemoveOnUninstall" />
            </RegistryKey>
          </RegistryKey>
        </RegistryKey>
        <?endforeach?>
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>

如果你想知道,这实际上是一个ASCOM望远镜驱动程序。

首先,我采纳了上面的建议,在一个单独的文件中创建了一些平台变量,你可以在XML中看到这些变量。

接近顶部的if-then-else部分处理x86 vs x64兼容性。我的程序集目标是“任何CPU”,所以在x64系统上,我需要注册它两次,一次在64位注册表中,一次在32位Wow6432Node区域中。if-then-else为我设置了这个,这些值稍后在foreach循环中使用。这样,我只需要编写一次注册表项(DRY原则)。

file元素指定实际安装和注册的程序集dll:

<File Id="filDriverAssembly" Source="$(var.TiGra.Astronomy.AWRDriveSystem.TargetPath)" KeyPath="yes" Vital="yes" Assembly=".net" AssemblyApplication="filDriverAssembly"  />

没有什么革命性的东西,但是请注意Assembly=".net" -这个属性本身就会导致程序集被放入GAC,这不是我想要的。使用AssemblyApplication属性指向它本身只是阻止Wix将文件放入GAC的一种方法。现在Wix知道它是一个。net程序集,但是,它允许我在XML中使用某些绑定器变量,例如!(bind.assemblyFullname.filDriverAssembly)来获取程序集的全名。

其他回答

设置IIS enable32BitAppOnWin64标志http://trycatchfail.com/blog/post/WiX-Snippet-change-enable32BitAppOnWin64.aspx

<InstallExecuteSequence>
   <RemoveExistingProducts After="InstallFinalize" />
   <Custom Action="ConfigureAppPool" After="InstallFinalize" >
     <![CDATA[NOT Installed AND VersionNT64 >= 600]]>         
   </Custom>
</InstallExecuteSequence>

<CustomAction Id="ConfigureAppPool" Return="check" Directory="TARGETDIR" ExeCommand="[SystemFolder]inetsrv\appcmd set apppool /apppool.name:[APPPOOLNAME] /enable32BitAppOnWin64:false" />

我很惊讶没有人提到在构建期间使用T4生成WXS文件。我是通过Henry Lee @ New Age Solutions了解到这一点的。

实际上,您创建了一个自定义MSBuild任务来执行T4模板,该模板在编译Wix项目之前输出WXS。这允许您(取决于您如何实现它)自动包含来自编译另一个解决方案的所有程序集输出(这意味着您不再需要在添加新程序集时编辑wxs)。

设置DISABLEADVTSHORTCUTS属性,强制安装程序中所有发布的快捷方式成为常规快捷方式,并且不需要包括一个虚拟的reg键作为小键盘。

<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>

我认为Windows Installer 4.0或更高版本是必需的。

这是一个很好的结构,但根据我的经验,我想知道你如何解决这些情况:

答:你的安装似乎都落在了同一个目的地。如果用户需要同时安装所有3个版本,您的进程是否允许这样做。它们能明确地说出它们正在触发的每个可执行文件的哪个版本吗?

B.如何处理TEST和/或TRAINING中存在但LIVE中还没有的新文件?

当安装不允许卸载或重新安装且不能回滚时,执行强制重新安装。 VBscript脚本,用于覆盖一个没有卸载的安装。

Dim objShell
set objShell = wscript.createObject("wscript.shell")

iReturn = objShell.Run("CMD /K MsiExec.exe /I ""C:\Users\TheUser\Documents\Visual Studio 2010\Projects\InstallationTarget\HelloInstaller\bin\Debug\HelloInstaller.msi"" REINSTALLMODE=vomus REINSTALL=ALL",,True)