当前位置:  开发笔记 > 编程语言 > 正文

WiX技巧和提示

如何解决《WiX技巧和提示》经验,为你挑选了23个好方法。

我们现在已经使用WiX一段时间了,尽管人们普遍抱怨易用性,但它还是相当不错.我正在寻找的是有用的建议:

设置WiX项目(布局,参考,文件模式)

将WiX集成到解决方案和构建/发布流程中

为新安装和升级配置安装程序

任何好的WiX黑客你都想分享

si618.. 157

    将变量保存在单独的wxi包含文件中.允许重复使用,变量查找速度更快,并且(如果需要)允许外部工具更容易操作.

    为x86和x64构建定义平台变量

    
    
      
      
      
    
      
      
      
    
    

    将安装位置存储在注册表中,启用升级以查找正确的位置.例如,如果用户设置自定义安装目录.

     
        
     
    

    注意:WiX大师Rob Mensching发布了一篇优秀的博客文章,该文章详细介绍了在命令行设置属性时的边缘情况.

    使用1. 2.和3的示例.

    
    
      
    

    
      
        
    

    最简单的方法是始终进行重大升级,因为它允许在单个MSI中进行新安装和升级.UpgradeCode固定为唯一的Guid,永远不会更改,除非我们不想升级现有产品.

    注意:在WiX 3.5中有一个新的MajorUpgrade元素,让生活更轻松!

    在"添加/删除程序"中创建图标

    
    
    
    

    在发布版本中,我们对安装程序进行版本控制,将msi文件复制到部署目录.使用从AfterBuild目标调用的wixproj目标的示例:

    
      
      
    
    

    使用heat来收集带有通配符(*)Guid的文件.如果您想在多个项目中重用WXS文件,则非常有用(请参阅我对同一产品的多个版本的回答).例如,此批处理文件会自动收集RoboHelp输出.

    @echo off  
    robocopy ..\WebHelp "%TEMP%\WebHelpTemp\WebHelp" /E /NP /PURGE /XD .svn  
    "%WIX%bin\heat" dir "%TEMP%\WebHelp" -nologo -sfrag -suid -ag -srd -dir WebHelp -out WebHelp.wxs -cg WebHelpComponent -dr INSTALLLOCATION -var var.WebDeploySourceDir 
    

    还有一点,robocopy在收获之前剥离Subversion工作副本元数据; 在-dr根目录引用设置为我们的安装位置,而不是默认TARGETDIR; -var用于创建变量以指定源目录(Web部署输出).

    通过使用Strings.wxl进行本地化,可以轻松地将产品版本包含在欢迎对话框标题中.(信用:saschabeaumont.添加,因为这个伟大的提示隐藏在评论中)

    
        {\WixUI_Font_Bigger}Welcome to the [ProductName] [ProductVersion] Setup Wizard
    
    

    为自己节省一些痛苦,并遵循Wim Coehen对每个文件一个组件的建议.这也允许您省略(或通配*)组件GUID.

    Rob Mensching有一种通过搜索快速跟踪MSI日志文件中的问题的简洁方法value 3.请注意有关国际化的评论.

    添加条件功能时,将默认功能级别设置为0(禁用)更直观,然后将条件级别设置为所需的值.如果您将默认功能级别设置为> = 1,则条件级别必须为0才能将其禁用,这意味着条件逻辑必须与您期望的相反,这可能会令人困惑:)

    
      NOT UPGRADEFOUND
    
    
      UPGRADEFOUND
    
    


Simon Steele.. 38

检查是否安装了IIS:


    



    Installed OR IIS_MAJOR_VERSION

检查Vista +上是否安装了IIS 6 Metabase兼容性:


    



    Installed OR ((VersionNT < 600) OR IIS_METABASE_COMPAT)

很有用.谢谢! (2认同)


Cheeso.. 34

将所有ID保存在不同的名称空间中

功能以F. 示例开头:F.Documentation,F.Binaries,F.SampleCode.

组件以C. Ex 开头:C.ChmFile,C.ReleaseNotes,C.LicenseFile,C.IniFile,C.Registry

CustomActions是CA. Ex:CA.LaunchHelp,CA.UpdateReadyDlg,CA.SetPropertyX

文件是 Fi.

目录是 Di.

等等.

我发现这有助于跟踪所有各种类别中的各种id.



1> si618..:

    将变量保存在单独的wxi包含文件中.允许重复使用,变量查找速度更快,并且(如果需要)允许外部工具更容易操作.

    为x86和x64构建定义平台变量

    
    
      
      
      
    
      
      
      
    
    

    将安装位置存储在注册表中,启用升级以查找正确的位置.例如,如果用户设置自定义安装目录.

     
        
     
    

    注意:WiX大师Rob Mensching发布了一篇优秀的博客文章,该文章详细介绍了在命令行设置属性时的边缘情况.

    使用1. 2.和3的示例.

    
    
      
    

    
      
        
    

    最简单的方法是始终进行重大升级,因为它允许在单个MSI中进行新安装和升级.UpgradeCode固定为唯一的Guid,永远不会更改,除非我们不想升级现有产品.

    注意:在WiX 3.5中有一个新的MajorUpgrade元素,让生活更轻松!

    在"添加/删除程序"中创建图标

    
    
    
    

    在发布版本中,我们对安装程序进行版本控制,将msi文件复制到部署目录.使用从AfterBuild目标调用的wixproj目标的示例:

    
      
      
    
    

    使用heat来收集带有通配符(*)Guid的文件.如果您想在多个项目中重用WXS文件,则非常有用(请参阅我对同一产品的多个版本的回答).例如,此批处理文件会自动收集RoboHelp输出.

    @echo off  
    robocopy ..\WebHelp "%TEMP%\WebHelpTemp\WebHelp" /E /NP /PURGE /XD .svn  
    "%WIX%bin\heat" dir "%TEMP%\WebHelp" -nologo -sfrag -suid -ag -srd -dir WebHelp -out WebHelp.wxs -cg WebHelpComponent -dr INSTALLLOCATION -var var.WebDeploySourceDir 
    

    还有一点,robocopy在收获之前剥离Subversion工作副本元数据; 在-dr根目录引用设置为我们的安装位置,而不是默认TARGETDIR; -var用于创建变量以指定源目录(Web部署输出).

    通过使用Strings.wxl进行本地化,可以轻松地将产品版本包含在欢迎对话框标题中.(信用:saschabeaumont.添加,因为这个伟大的提示隐藏在评论中)

    
        {\WixUI_Font_Bigger}Welcome to the [ProductName] [ProductVersion] Setup Wizard
    
    

    为自己节省一些痛苦,并遵循Wim Coehen对每个文件一个组件的建议.这也允许您省略(或通配*)组件GUID.

    Rob Mensching有一种通过搜索快速跟踪MSI日志文件中的问题的简洁方法value 3.请注意有关国际化的评论.

    添加条件功能时,将默认功能级别设置为0(禁用)更直观,然后将条件级别设置为所需的值.如果您将默认功能级别设置为> = 1,则条件级别必须为0才能将其禁用,这意味着条件逻辑必须与您期望的相反,这可能会令人困惑:)

    
      NOT UPGRADEFOUND
    
    
      UPGRADEFOUND
    
    



2> Simon Steele..:

检查是否安装了IIS:


    



    Installed OR IIS_MAJOR_VERSION

检查Vista +上是否安装了IIS 6 Metabase兼容性:


    



    Installed OR ((VersionNT < 600) OR IIS_METABASE_COMPAT)


很有用.谢谢!

3> Cheeso..:

将所有ID保存在不同的名称空间中

功能以F. 示例开头:F.Documentation,F.Binaries,F.SampleCode.

组件以C. Ex 开头:C.ChmFile,C.ReleaseNotes,C.LicenseFile,C.IniFile,C.Registry

CustomActions是CA. Ex:CA.LaunchHelp,CA.UpdateReadyDlg,CA.SetPropertyX

文件是 Fi.

目录是 Di.

等等.

我发现这有助于跟踪所有各种类别中的各种id.



4> Peter Tate..:

很棒的问题.我很想看到一些最佳实践.

我分发了很多文件,因此我将项目设置为几个wxs源文件.

我有一个顶级源文件,我称之为Product.wxs,它基本上包含安装结构,但不包含实际组件.该文件有几个部分:


  
    ... 
   s ...
   
    
        ...
   
   
       A bunch of these that
   
   
   
   
   

其余的.wix文件由包含ComponentGroups的Fragments组成,这些ComponentGroups在Product.wxs的Feature标记中引用.我的项目包含我分发的文件的一个很好的逻辑分组


   
     
     ....
    
    
      

这并不完美,我的OO蜘蛛感觉有点刺痛,因为片段必须引用Product.wxs文件中的名称(例如DirectoryRef),但我发现维护单个大型源文件更容易.

我很乐意听到这方面的评论,或者是否有人也有任何好的提示!



5> Cheeso..:

在退出对话框中添加一个复选框以启动应用程序或帮助文件.

...










  WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT

如果你这样做,"标准"外观并不完全正确.复选框始终为灰色背景,而对话框为白色:

alt text http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_1.gif

解决此问题的一种方法是指定您自己的自定义ExitDialog,其中包含位置不同的复选框.这可行,但似乎只是为了改变一个控件的颜色很多工作.解决同一问题的另一种方法是对生成的MSI进行后处理,以更改特定CheckBox控件的Control表中的X,Y字段.javascript代码如下所示:

var msiOpenDatabaseModeTransact = 1;
var filespec = WScript.Arguments(0);
var installer = new ActiveXObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql = "UPDATE `Control` SET `Control`.`Height` = '18', `Control`.`Width` = '170'," +
          " `Control`.`Y`='243', `Control`.`X`='10' " +
          "WHERE `Control`.`Dialog_`='ExitDialog' AND " + 
          "  `Control`.`Control`='OptionalCheckBox'";
var view = database.OpenView(sql);
view.Execute();
view.Close();
database.Commit();

在生成MSI之后(从light.exe)将此代码作为命令行脚本(使用cscript.exe)运行将生成看起来更专业的ExitDialog:

alt text http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_2.gif



6> si618..:

使用相同的源文件创建Live,Test,Training,...版本.

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

先决条件

MSBuild社区任务

假设

WiX变量用于定义UpgradeCode,ProductName,InstallName.

您已有一个正常工作的安装程序 直到你这样做我才会尝试.

所有组件都保存在一个文件中(Components.wxs).如果您有多个文件,此过程将起作用,只需要做更多工作.

目录结构

Setup.Library

所有wxs文件(组件,功能,UI对话框,......)

Common.Config.wxi(ProductCode ="*",ProductVersion,PlatformProgramFilesFolder,...)

Setup.Live(wixproj)

使用"添加现有文件" - >"添加为链接"链接所有Setup.Library文件(Visual Studio中"添加"按钮旁边的小向下箭头按钮)

Config.wxi(具有唯一的UpgradeCode,ProductName,InstallName,...)

Setup.Test,...

根据实时但Config.wxi配置为测试环境.

处理

创建Setup.Library目录并从现有项目中移动所有wxs和wxi文件(Config.wxi除外).

按照正常的wixproj创建Setup.Live,Setup.Test等.

在Setup.Live等中的wixproj中添加BeforeBuild目标,以执行MSBuild社区任务FileUpdate来修改Guids(我使用A代表Live,B代表测试,C代表培训)

添加AfterBuild目标以将Components.wxs Guids恢复为0.

使用Orca验证每个MSI中的每个组件都具有已修改的guid.

验证原始guid是否已恢复.

验证每个MSI是否正在安装(和升级)正确的产品和位置.

示例Config.wxi








  
  

  












示例Config.Common.wxi















   
   

   
   












示例Components.wxs



  
  
  
  
    
      
        
          
          ...

注意:我现在建议将Guid属性从Component(相当于*)中删除,每个组件使用一个文件并将文件设置为keypath.这消除了下面显示的调用ModifyComponentsGuidsRevertComponentsGuids目标的需要.但是,对于所有组件,这可能是不可能的.

示例Setup.Live.wixproj



  


  



  



  

最后的想法

此过程还应该用于为同一安装程序创建不同的合并模块(实时,测试,...作为功能)的不同安装程序.我选择了不同的安装程序,因为它似乎是一个更安全的选择,如果有人可能升级Live而不是Training,如果他们在同一个盒子上而你只是使用不同的合并模块的功能.

如果您使用MSI执行升级以及新安装(即仅主要升级方法),并将安装位置保存在注册表中,请记住为每个安装的密钥名称创建一个变量.

我们还在每个Config.wxi中创建变量,以便为每个安装程序启用唯一的虚拟目录名称,应用程序池,数据库名称等.

更新1: 如果为每个文件创建Guid ="*"的组件,将文件设置为keypath,则自动生成组件Guids将无需调用FileUpdate任务.

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

更新3:找到一种方法来消除对svn:externals和临时文件创建的依赖.这使得构建过程更具弹性(如果您不能使用Guids通配符,则是最佳选择),如果光线或蜡烛中存在构建失败,则可以减少脆弱性.

更新4:使用实例转换支持多个实例是在WiX 3.0+中,绝对值得一看.



7> Cheeso..:

使用Javascript CustomActions,因为它们太简单了

人们说Javascript是用于MSI CustomActions的错误.给出的理由:难以调试,难以使其可靠.我不同意.调试并不难,当然也不比C++更难.它与众不同.我发现在Javascript中编写CustomActions比使用C++更容易,更容易.快多了.同样可靠.

只有一个缺点:Javascript CustomActions可以通过Orca提取,而C/C++ CA则需要逆向工程.如果您认为您的安装程序魔法是受保护的知识产权,您将需要避免使用脚本.

如果使用脚本,则只需要从一些结构开始.这里有一些让你入门.


CustomAction的Javascript"样板"代码:

//
// CustomActions.js 
// 
// Template for WIX Custom Actions written in Javascript.
// 
// 
// Mon, 23 Nov 2009  10:54
// 
// ===================================================================


// 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 MyCustomActionInJavascript_CA() {
    try {
        LogMessage("Hello from MyCustomActionInJavascript");
        // ...do work here...
        LogMessage("Goodbye from MyCustomActionInJavascript");
    }
    catch (exc1) {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException(exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}

// Pop a message box.  also spool a message into the MSI log, if it is enabled. 
function LogException(exc) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction: Exception: 0x" + decimalToHexString(exc.number) + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}


// spool an informational message into the MSI log, if it is enabled. 
function LogMessage(msg) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction:: " + msg;
    Session.Message(MsgKind.Log, record);
}


// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var WindowStyle = {
    Hidden : 0,
    Minimized : 1,
    Maximized : 2
};

// http://msdn.microsoft.com/en-us/library/314cz14s(v=VS.85).aspx
var OpenMode = {
    ForReading : 1,
    ForWriting : 2,
    ForAppending : 8
};

// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var SpecialFolders = {
    WindowsFolder : 0, 
    SystemFolder :  1, 
    TemporaryFolder : 2
};

// Run a command via cmd.exe from within the MSI
function RunCmd(command)
{
    var wshell = new ActiveXObject("WScript.Shell");
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder);
    var tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName());

    LogMessage("shell.Run("+command+")");

    // use cmd.exe to redirect the output
    var rc = wshell.Run("%comspec% /c " + command + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    // here, optionally parse the output of the command 
    if (parseOutput) {
        var textStream = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
        while (!textStream.AtEndOfStream) {
            var oneLine = textStream.ReadLine();
            var line = ParseOneLine(oneLine);
                ...
        }
        textStream.Close();
    }

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }

    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}

然后,使用以下内容注册自定义操作:


  

  


当然,您可以根据需要插入多个Javascript函数,以进行多个自定义操作.一个例子:我使用Javascript在IIS上进行WMI查询,以获取可以安装ISAPI过滤器的现有网站列表.然后使用此列表填充稍后在UI序列中显示的列表框.一切都很容易.

在IIS7上,没有用于IIS的WMI提供程序,因此我使用该shell.Run()方法调用appcmd.exe来执行工作.简单.

相关问题:关于Javascript CustomActions


+1我发现DTF方法很容易设置,但javascript也很有用.

8> Terrance..:

使用Msi Diagnostic日志记录获取详细的故障信息

msiexec /i Package.msi /l*v c:\Package.log

哪里

Package.msi
是你的包的名称和
c:\Package.log
是您希望输出日志的位置

Msi错误代码

Wix介绍视频
哦和随机Wix介绍视频特色"先生WiX"Rob Mensching是"概念大图"有用.


WiX可以.设置MsiLogging属性.仅受Windows Installer 4.0+支持.
+1如果我们可以从Wix而不是命令行启用日志记录会好得多.

9> Wim Coenen..:

Peter Tate已经展示了如何在单独的wix片段中定义可重用的ComponentGroup定义.与此相关的一些额外技巧:

目录别名

组件组片段不需要知道主产品wxs定义的目录.在组件组片段中,您可以讨论如下文件夹:


...

然后主产品可以将其目录之一(例如"productInstallFolder")替换为:


   
    
    

依赖图

ComponentGroup元素可以包含ComponentGroupRef子元素.如果您有一大堆可重用组件,并且它们之间具有复杂的依赖关系图,那么这非常有用.您只需在每个组件的自己的片段中设置一个ComponentGroup,并声明依赖关系,如下所示:


   
   

如果您现在在设置中引用组件组"B",因为它是您的应用程序的直接依赖项,它将自动拉入组件组"A",即使应用程序作者从未意识到它是"B"的依赖项.只要你没有任何循环依赖,它就"正常工作".

可重复使用的wixlib

如果您使用lit.exe将big-pool-o-reusable-components编译为可重用的wixlib,则上述依赖关系图的想法最有效.在创建应用程序设置时,您可以像wixobj文件一样引用此wixlib.candle.exe链接器将自动消除主产品wxs文件未"拉入"的任何片段.



10> Peter T. LaC..:

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

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


对于未来的访问者,Wix 3.5有一个实用程序[heat.exe](http://wix.sourceforge.net/manual-wix3/heat.htm)自动执行此操作
+1这真的很好,我并不担心程序集,但我们的Web项目可能会遇到问题,aspx页面和其他工件(图像,css)被添加到项目但不是WiX.

11> Terrance..:

使用Heat.exe粉碎脸部并在痛苦的大型安装上造成"Epic Pwnage"

扩展了Si和 Robert-P关于热量的答案.

翻译:(使用热量来避免手动将单个文件键入项目,并自动化构建以实现整体更简单的过程.)

WiX 2.0 Heat Syntax详细说明

对于较新的版本(并不是与旧版本有所不同,但有可能令人烦恼的语法更改....)转到目录Heat来自cmd.exe,只需输入热量,但我有一个示例,请在这里寻求帮助如果需要,可以使用更新版本.

将以下内容添加到visual studio 2010中的构建事件中.
(右键单击项目 - >属性 - >构建事件 - >预构建事件)

$(WIX)bin\heat.exe" dir "$(EnviromentVariable)" -cg GroupVariable -gg -scom -sreg -sfrag - srd -dr INSTALLLOCATION -var env.LogicPath -out "$(FragmentDir)\FileName.wxs

-gg 

在运行热量时生成Guids(如执行上述命令时)

-scom 

不要抓"COM文件"

-sreg 

不要抓"注册表文件"

-sfrag 

别拿"碎片"

-srd 

不要抓住"根目录"

dir

dir表示你希望Heat在文件夹中查找

"$(EnviromentVariable)"

要添加到预处理器变量的变量的名称(右键单击项目,转到属性)项目属性 - >构建部分,其中显示定义预处理器变量(假定visual studio 2010)

Example:
EnviromentVariable=C:\Project\bin\Debug;
没有双引号但以分号结尾

-cg GroupVariable 

将从创建到主wxs文件的片段引用的ComponentGroup

FragmentDir

将存储输出wxs片段的片段目录

FileName.wxs

文件的名称

这里有完整的教程,所以非常有帮助

第1 部分第2部分



12> Robert P..:

包括COM对象:

heat生成所有大多数(如果不是全部)注册表项和它们所需的其他配置.麾!

包括托管COM对象(又名.NET或C#COM对象)

使用heat托管的COM对象会给你一个几乎完全威克斯文件.

如果您不需要GAC中提供的库(即,全局可用:大多数时候您还不需要使用.NET程序集 - 如果不是这样的话,您可能在这一点上做错了您需要确保更新CodeBase要设置的注册表项[#ComponentName].如果您计划将其安装到GAC(例如,您已经创建了一些每个人都想要使用的新的通用库),则必须删除此条目,并向该File元素添加两个新属性:AssemblyKeyPath.程序集应设置为".net",并KeyPath应设置为"是".

但是,某些环境(尤其是具有托管内存的任何环境,如脚本语言)也需要访问Typelib. 确保heat在您的typelib 上运行并包含它. heat将生成所有需要的注册表项.多么酷啊?



13> gehho..:

安装到 C:\ProductName

某些应用程序需要安装到C:\ProductName类似的东西,但99.9%(如果不是100%)的网络安装示例C:\Program Files\CompanyName\ProductName.

以下代码可用于将TARGETDIR属性设置为C:驱动器的根目录(取自WiX用户列表):



    TARGETDIR=""


    TARGETDIR=""

注意:默认情况下,TARGETDIR 指向C:\!它ROOTDRIVE反过来指向哪个反过来指向具有最多可用空间的驱动器(见这里) - 这不一定是C:驱动器.可能有另一个硬盘驱动器,分区或USB驱动器!

然后,在标记下方的某处,您需要照常使用以下目录标记:


    
        
    



14> Robert P..:

环境变量

将Wxs文档编译为wixobj代码时,可以使用环境变量来确定各种信息.例如,假设您要更改项目中包含的文件.假设您有一个名为RELEASE_MODE的环境变量,您可以在构建MSI之前进行设置(使用脚本或手动,无关紧要)在wix源代码中,您可以执行以下操作:


然后在你的代码中,使用它来实时更改你的wxs文档,例如:




15> BozoJoe..:

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

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



16> 小智..:

为没有Votive的托管代码(C#)编写的WIX创建自定义操作

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



17> 小智..:

编辑对话框

一个很好的编辑对话框的能力是在版本4.0.1.7090(或更高版本)中使用SharpDevelop.借助此工具,可以在"设计"视图中打开,预览和编辑独立对话框(来自WiX源的wxs文件,例如InstallDirDlg.wxs).



18> EdmundYeung9..:

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


   
   
     = 600]]>         
   





19> thijs..:

我们在GUI的第一个屏幕中显示产品版本(微小).因为人们每次都选择正确的版本时会犯错误.(并让我们的开发人员搜索年龄..)

我们已经设置了TFSBuild来生成变换(.mst文件)以及我们不同环境的配置.(我们了解需要部署的所有环境).

由于格兰特霍利迪的原始博客帖子已关闭,我复制其内容粘贴在这里:


MSBuild任务从XMLMarch 11 2008生成MSI转换文件

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

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

    它们是二进制格式

    您无法"编辑"或"查看"转换文件.您必须应用它或重新创建它以查看它包含的更改.

幸运的是,我们可以使用Microsoft Windows Installer对象库(c:windowssystem32msi.dll)打开MSI"数据库"并创建转换文件.

积分再次转向Alex Shevchuk - 从MSI到WiX - 第7部分 - 使用Transforms自定义安装,向我们展示如何使用VbScript实现此目的.基本上我所做的就是采用Alex的例子并使用Interop.WindowsInstaller.dll我实现了一个MSBuild任务.MSBuild任务

在这里下载源代码和示例transforms.xml(~7Kb Zipped VS2008 Solution)



我们在本地化文件中重新定义WelcomeDlgTitle - 效果很好! {\ WixUI_Font_Bigger}欢迎使用[ProductName] [ProductVersion]安装向导

20> Cheeso..:

修改"准备安装?" 对话框(又名VerifyReadyDlg)提供所做选择的摘要.

它看起来像这样:
alt text 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:


  

  


将CA附加到按钮.在此示例中,从CustomizeDlg单击Next时将触发CA:


  


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



21> Dave Anderse..:

将可能在其自己的碎片中单独修补的组件放入其中

如果您在片段中包含任何组件,则必须包含产品安装程序和修补程序,您必须包含该片段中的所有组件.在构建安装程序的情况下,如果您错过任何组件引用,您将从light.exe获得链接错误.但是,在创建补丁时,如果在片段中包含单个组件引用,则该片段中的所有已更改组件都将显示在补丁中.

像这样:


    
        
            
        
    



    
        
           
        
    



    
        
           
        
    

而不是这个:


    
        
            
        

        
           
        

        
           
        
    

此外,在使用WiX.chm帮助文件中的"使用Purely WiX"主题进行修补时,使用此过程生成修补程序:

torch.exe -p -xi 1.0\product.wixpdb 1.1\product.wixpdb -out patch\diff.wixmst
candle.exe patch.wxs
light.exe patch.wixobj -out patch\patch.wixmsp
pyro.exe patch\patch.wixmsp -out patch\patch.msp -t RTM patch\diff.wixmst

仅使用单独片段中的组件构建的product.wixpdb的1.1版本是不够的.因此,请确保在发货前正确分割您的产品.



22> farfareast..:

从Wix3.0及更高版本打印EULA

1)编译wix源代码时,light.exe必须在命令行中引用WixUIExtension.dll.使用命令行开关-ext.

2)如果你添加对WixUIExtension.dll的引用,你的项目无法编译,这很可能是因为Dialog ID的冲突,即你的项目使用与WixUIExtension.dll中的一些标准对话框相同的对话框ID,为对话框提供不同的ID.这是很常见的问题.

3)您的许可证对话框必须具有ID为"LicenseText"的ScrollableText控件.Wix在打印时会搜索该控件的名称.


    

和一个引用自定义动作的PushButton


    1

4)使用Id ="PrintEula"定义CustomAction,如下所示:


注意:与Wix2.0相比,Wix3.0中的BinaryKey不同,并且必须完全是"WixUIWixca"(区分大小写).

当用户按下按钮时,他/她将看到标准的选择打印机对话框,并且可以从那里打印.



23> 小智..:

在部署安装包之前,我总是控制它的内容.

这只是在命令行(根据Terrences帖子)打开命令行并输入的简单调用

msiexec /a Package.msi /qb TARGETDIR="%CD%\Extract" /l*vx "%CD\install.log%"

这将使用当前路径将包内容提取到子目录"Extract".

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有