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

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


当前回答

修改“准备好安装了吗?”对话框(又名VerifyReadyDlg),以提供所做选择的摘要。

它是这样的: Alt文本http://i46.tinypic.com/s4th7t.jpg

用Javascript CustomAction来做这个:


Javascript代码:

// http://msdn.microsoft.com/en-us/library/aa372516(VS.85).aspx
var MsiViewModify = 
    {
        Refresh          : 0,
        Insert           : 1,
        Update           : 2,
        Assign           : 3,
        Replace          : 4,
        Merge            : 5,
        Delete           : 6,
        InsertTemporary  : 7,   // cannot permanently modify the MSI during install
        Validate         : 8,
        ValidateNew      : 9,
        ValidateField    : 10,
        ValidateDelete   : 11
    };


// http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx
var Buttons = 
    {
        OkOnly           : 0,
        OkCancel         : 1,
        AbortRetryIgnore : 2,
        YesNoCancel      : 3
    };

var Icons= 
    {
        Critical         : 16,
        Question         : 32,
        Exclamation      : 48,
        Information      : 64
    }

var MsgKind =
    {
        Error            : 0x01000000,
        Warning          : 0x02000000,
        User             : 0x03000000,
        Log              : 0x04000000
    };

// http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx
var MsiActionStatus = 
    {
        None             : 0,
        Ok               : 1, // success
        Cancel           : 2,
        Abort            : 3,
        Retry            : 4, // aka suspend?
        Ignore           : 5  // skip remaining actions; this is not an error.
    };

function UpdateReadyDialog_CA(sitename)
{
    try 
    {
        // can retrieve properties from the install session like this:
        var selectedWebSiteId = Session.Property("MSI_PROPERTY_HERE");

        // can retrieve requested feature install state like this:
        var fInstallRequested   = Session.FeatureRequestState("F.FeatureName");

        var text1 = "This is line 1 of text in the VerifyReadyDlg";

        var text2 = "This is the second line of custom text";

        var controlView     = Session.Database.OpenView("SELECT * FROM Control");
        controlView.Execute();

        var rec             = Session.Installer.CreateRecord(12);
        rec.StringData(1)   = "VerifyReadyDlg";    // Dialog_
        rec.StringData(2)   = "CustomVerifyText1"; // Control - can be any name
        rec.StringData(3)   = "Text";              // Type
        rec.IntegerData(4)  = 25;                  // X
        rec.IntegerData(5)  = 60;                  // Y
        rec.IntegerData(6)  = 320;                 // Width
        rec.IntegerData(7)  = 85;                  // Height
        rec.IntegerData(8)  = 2;                   // Attributes
        rec.StringData(9)   = "";                  // Property
        rec.StringData(10)  = vText1;              // Text
        rec.StringData(11)  = "";                  // Control_Next
        rec.StringData(12)  = "";                  // Help
        controlView.Modify(MsiViewModify.InsertTemporary, rec);

        rec                 = Session.Installer.CreateRecord(12);
        rec.StringData(1)   = "VerifyReadyDlg";    // Dialog_
        rec.StringData(2)   = "CustomVerifyText2"; // Control - any unique name
        rec.StringData(3)   = "Text";              // Type
        rec.IntegerData(4)  = 25;                  // X
        rec.IntegerData(5)  = 160;                 // Y
        rec.IntegerData(6)  = 320;                 // Width
        rec.IntegerData(7)  = 65;                  // Height
        rec.IntegerData(8)  = 2;                   // Attributes
        rec.StringData(9)   = "";                  // Property
        rec.StringData(10)  = text2;               // Text
        rec.StringData(11)  = "";                  // Control_Next
        rec.StringData(12)  = "";                  // Help
        controlView.Modify(MsiViewModify.InsertTemporary, rec);

        controlView.Close();
    }
    catch (exc1)
    {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException("UpdatePropsWithSelectedWebSite", exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}


function LogException(loc, exc)
{
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "Exception {" + loc + "}: " + exc.number + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}

声明Javascript CA:

<Fragment>
  <Binary Id="IisScript_CA" SourceFile="CustomActions.js" />

  <CustomAction Id="CA.UpdateReadyDialog"
              BinaryKey="IisScript_CA"
              JScriptCall="UpdateReadyDialog_CA"
              Execute="immediate"
              Return="check" />
</Fragment>

将CA连接到按钮上。在这个例子中,当从CustomizeDlg中单击Next时,CA将被触发:

<UI ...>
  <Publish Dialog="CustomizeDlg" Control="Next" Event="DoAction" 
           Value="CA.UpdateReadyDialog" Order="1"/>
</UI>

相关SO问题:如何设置,在运行时,文本将显示在VerifyReadyDlg?

其他回答

使用RobM特殊的“记住属性”模式

http://robmensching.com/blog/posts/2010/5/2/The-WiX-toolsets-Remember-Property-pattern

环境变量

在将Wxs文档编译为wixobj代码时,可以使用环境变量来确定各种信息。例如,假设您想要更改项目中包含的文件。让我们假设你有一个名为RELEASE_MODE的环境变量,你在构建MSI之前设置了它(无论是用脚本还是手动设置,都没关系)在你的wix源代码中,你可以这样做:

<define FILESOURCE = c:\source\output\bin\$(env.RELEASE_MODE) >

然后在稍后的代码中,在适当的地方使用它来动态地更改WXS文档,例如:

<Icon Id="myicon.ico" SourceFile="$(var.FILESOURCE)" />

我们将产品版本显示在GUI的第一个屏幕的某个位置(很小)。因为人们每次都倾向于在选择正确版本时犯错误。(这让我们开发人员找了很长时间。) 我们已经设置了TFSBuild来生成转换(。MST文件)为我们不同的环境配置。(我们知道需要部署到的所有环境)。

由于Grant Holliday的原始博客帖子已经关闭,我复制粘贴了它的内容:


MSBuild任务从xml3月11日2008生成MSI转换文件

在我之前的文章中,我描述了如何使用MSI Transform (*.mst)文件将特定于环境的配置设置从通用MSI包中分离出来。

尽管这为您的配置提供了一定程度的灵活性,但Transform文件有两个缺点:

它们是二进制格式的 您不能“编辑”或“查看”转换文件。您必须应用它或重新创建它,以查看它包含哪些更改。

幸运的是,我们可以使用Microsoft Windows安装程序对象库(c:windowssystem32msi.dll)打开MSI“数据库”并创建转换文件。

感谢Alex Shevchuk -从MSI到WiX -第7部分-使用转换自定义安装,向我们展示如何用VbScript实现这一点。基本上,我所做的就是以Alex为例,使用Interop.WindowsInstaller.dll实现了一个MSBuild任务。 MSBuild任务

下载源代码和示例transforms.xml (~7Kb压缩VS2008解决方案)


当安装不允许卸载或重新安装且不能回滚时,执行强制重新安装。 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)

包括COM对象:

Heat生成所有(如果不是全部)注册表项和它们所需的其他配置。喜乐!

包括托管COM对象(又名。net或c# COM对象)

在托管COM对象上使用heat将为您提供一个几乎完整的wix文档。

If you don't need the library available in the GAC (ie, globally available: MOST of the time you do not need this with your .NET assemblies anyway - you've probably done something wrong at this point if it's not intended to be a shared library) you will want to make sure to update the CodeBase registry key to be set to [#ComponentName]. If you ARE planning on installing it to the GAC (eg, you've made some new awesome common library that everyone will want to use) you must remove this entry, and add two new attributes to the File element: Assembly and KeyPath. Assembly should be set to ".net" and KeyPath should be set to "yes".

然而,某些环境(特别是带有托管内存的环境,如脚本语言)也需要访问Typelib。确保在你的打字单上运行热度并包括它。Heat将生成所有需要的注册表项。多酷啊!