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

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


当前回答

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

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

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

其他回答

创建现场、测试、培训……使用相同源文件的版本。

简而言之:为每个安装程序创建唯一的UpgradeCode,并自动为每个安装程序定义每个Guid的第一个字符,其余31个字符是唯一的。

先决条件

MSBuild社区任务

假设

WiX变量用于定义UpgradeCode、ProductName、InstallName。 您已经有了一个工作的安装程序。你不动手我是不会动手的。 所有组件都保存在一个文件(Components.wxs)中。如果你有多个文件,这个过程是有效的,只是有更多的工作要做。

目录结构

设置。图书馆 所有wxs文件(组件,功能,UI对话框,…) Common.Config.wxi (ProductCode="*", ProductVersion, PlatformProgramFilesFolder,…) 设置。生活(wixproj) 链接所有安装程序。“添加为链接”(Visual Studio中“添加”按钮旁边的向下箭头按钮) 配置。wxi(有唯一的UpgradeCode, ProductName, InstallName,…) 设置。测试,… 按live但配置。wxi为测试环境配置。

过程

Create Setup.Library directory and move all your wxs and wxi files (except Config.wxi) from existing project. Create Setup.Live, Setup.Test, etc as per normal wixproj. Add BeforeBuild target in wixproj in Setup.Live, etc to perform MSBuild Community Task FileUpdate to modify Guids (I used A for Live, B for Test and C for training) Add AfterBuild target to revert Components.wxs Guids back to 0. Verify with Orca that each component in each MSI has the modified guid. Verify that original guids are restored. Verify that each MSI is installing (and upgrading) correct product and location.

例子Config.wxi

<?xml version="1.0" encoding="utf-8"?>
<Include>
<!-- Upgrade code should not change unless you want to install 
     a new product and have the old product remain installed, 
     that is, both products existing as separate instances. -->
<?define UpgradeCode = "YOUR-GUID-HERE" ?>

<!-- Platform specific variables -->
<?if $(var.Platform) = x64 ?>
  <!-- Product name as you want it to appear in Add/Remove Programs-->
  <?define ProductName = "Foo 64 Bit [Live]" ?>
<?else ?>
  <?define ProductName =  "Foo [Live]" ?>
<?endif ?>

<!-- Directory name used as default installation location -->
<?define InstallName = "Foo [Live]" ?>

<!-- Registry key name used to store installation location -->
<?define InstallNameKey = "FooLive" ?>

<?define VDirName = "FooLive" ?>
<?define AppPoolName = "FooLiveAppPool" ?>
<?define DbName = "BlahBlahLive" ?>
</Include>

例子Config.Common.wxi

<?xml version="1.0" encoding="utf-8"?>
<Include>
<!-- Auto-generate ProductCode for each build, release and upgrade -->
<?define ProductCode = "*" ?>

<!-- Note that 4th version (Revision) is ignored by Windows Installer -->
<?define ProductVersion = "1.0.0.0" ?>

<!-- Minimum version supported if product already installed and this is an upgrade -->
<!-- Note that 4th version (Revision) is ignored by Windows Installer -->
<?define MinimumUpgradeVersion = "0.0.0.0" ?>

<!-- Platform specific variables -->
<?if $(var.Platform) = x64 ?>
   <?define Win64 = "yes" ?>
   <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else ?>
   <?define Win64 = "no" ?>
   <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif ?>

<?define ProductManufacturer = "Foo Technologies"?>

<!-- Decimal Language ID (LCID) for the Product. Used for localization. -->
<?define ProductLanguage = "1033" ?>

<?define WebSiteName = "DefaultWebSite" ?>
<?define WebSitePort = "80" ?>

<?define DbServer = "(local)" ?>
</Include>

例子Components.wxs

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <!-- The pre-processor variable which allows the magic to happen :) -->
  <?include $(sys.CURRENTDIR)\Config.wxi?>
  <?include ..\Setup.Library\Config.Common.wxi?>
  <Fragment Id="ComponentsFragment">
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="$(var.InstallName)">
          <Component Id="ProductComponent" Guid="0XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" KeyPath="yes">
          ...

注意:我现在建议将Guid属性从Component中去掉(相当于*),每个组件使用一个文件,并将文件设置为小键盘。这样就不需要调用如下所示的ModifyComponentsGuids和RevertComponentsGuids目标。不过,这可能不适用于您的所有组件。

例子Setup.Live.wixproj

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="BeforeBuild">
  <CallTarget Targets="ModifyComponentsGuids" />
</Target>
<Target Name="AfterBuild">
  <CallTarget Targets="RevertComponentsGuids" />
</Target>
<!-- Modify the first character of every Guid to create unique value for Live, Test and Training builds -->
<Target Name="ModifyComponentsGuids">
  <FileUpdate Files="..\Setup.Library\Components.wxs" Regex="Guid=&quot;([a-f]|[A-F]|\d)" ReplacementText="Guid=&quot;A" />
</Target>
<!-- Revert the first character of every Guid back to initial value -->
<Target Name="RevertComponentsGuids">
  <FileUpdate Files="..\Setup.Library\Components.wxs" Regex="Guid=&quot;([a-f]|[A-F]|\d)" ReplacementText="Guid=&quot;0" />
</Target>

最终的想法

This process should also work for creating different installers for different merge modules (Live, Test, ... as features) for the same installer. I went with different installers as it seemed a safer option, there is more risk that someone might upgrade Live instead of Training if they're on the same box and you just use features for the different merge modules. If you use your MSI to perform upgrades as well as new installs i.e. the major upgrade only approach, and you save your installation location in the registry, remember to create a variable for the key name for each install. We also create variables in each Config.wxi to enable unique virtual directory names, application pools, database names, et cetera for each installer.

更新1:如果您为每个文件创建带有Guid="*"的组件,并将文件设置为小键盘,则自动生成组件Guid将不需要调用FileUpdate任务。

更新2:我们遇到的一个问题是,如果您没有自动生成组件Guid,并且构建失败,那么临时文件需要手动删除。

更新3:找到了一种方法来消除对svn的依赖:externals和临时文件创建。这使得构建过程更具弹性(如果您不能通配符您的guid,这是最好的选择),并且在灯光或蜡烛中构建失败时不那么脆弱。

更新4:WiX 3.0+支持使用实例转换的多实例,当然也值得一看。

修复ProgressDlg,使其正确显示。

我将安装程序的字体大小从8增加到10,以使字体在高分辨率显示器上更人性化、更实用。我用这个XML魔法做到这一点:

<UI Id="MyCustomUI">
  <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="10" />
  <TextStyle Id="WixUI_Font_Big"    FaceName="Tahoma" Size="12" />
  <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="14" />
  <TextStyle Id="WixUI_Font_Title"  FaceName="Tahoma" Size="12" Bold="yes" />

  <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
</UI>

但这意味着ProgressDlg将无法正常显示。这是一个显示安装进度的程序,就在最后。ActionText被剪切,因此g和j等字母的下移不显示。在后处理Javascript中,通过调整Progressdialog中各种控件的大小和位置来解决这个问题。生成MSI后运行这个脚本:

var msiOpenDatabaseModeTransact = 1;
var filespec = WScript.Arguments(0);
var installer = new ActiveXObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

// The text on the exit dialog is too close to the title.  This 
// step moves the text down from Y=70 to Y=90, about one line. 
sql = "UPDATE `Control` SET `Control`.`Y` = '90' " +
    "WHERE `Control`.`Dialog_`='ExitDialog' AND `Control`.`Control`='Description'";
view = database.OpenView(sql);
view.Execute();
view.Close();

// The progressbar is too close to the status text on the Progress dialog. 
// This step moves the progressbar down from Y=115 to Y=118, about 1/3 line. 
sql = "UPDATE `Control` SET `Control`.`Y` = '118' " +
    "WHERE `Control`.`Dialog_`='ProgressDlg' AND `Control`.`Control`='ProgressBar'";
view = database.OpenView(sql);
view.Execute();
view.Close();

// The StatusLabel and ActionText controls are too short on the Progress dialog,
// which means the bottom of the text is cut off.  This step
// increases the height from 10 to 16.
sql = "UPDATE `Control` SET `Control`.`Height` = '16' " +
    "WHERE `Control`.`Dialog_`='ProgressDlg' AND `Control`.`Control`='StatusLabel'";
view = database.OpenView(sql);
view.Execute();
view.Close();
sql = "UPDATE `Control` SET `Control`.`Height` = '16' " +
    "WHERE `Control`.`Dialog_`='ProgressDlg' AND `Control`.`Control`='ActionText'";
view = database.OpenView(sql);
view.Execute();
view.Close();

database.Commit();

创建WIX的自定义动作,用托管代码(c#)编写,不带Votive

http://www.codeproject.com/KB/install/wixcustomaction.aspx

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

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

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

使用InstEd代替ORCA,这是一个查看MSI表的好工具。此外,它还具有区分两个包的能力 比较…

此外,一个附加版本与额外的功能是可用的。但免费版也为逆戟鲸提供了一个很好的选择。