WiX 技巧和技巧
我们已经使用 WiX 一段时间了,尽管人们常常抱怨其易用性,但它的运行情况相当不错。 我正在寻找的是关于以下方面的有用建议:
- 设置 WiX 项目(布局、引用、文件模式)
- 将 WiX 集成到解决方案以及构建/发布流程
- 为新安装和升级配置安装程序
- 您想要的任何好的 WiX hack分享
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
使用 Javascript CustomActions 因为它们太简单了
人们说过Javascript 不适用于 MSI CustomActions。 给出的原因是:难以调试、难以使其可靠。 我不同意。 调试并不难,当然不比 C++ 难。 只是不同而已。 我发现用 Javascript 编写 CustomActions 非常简单,比使用 C++ 容易得多。 快多了。 并且同样可靠。
只有一个缺点:Javascript CustomActions 可以通过 Orca 提取,而 C/C++ CA 则需要逆向工程。 如果您认为您的安装程序魔法受到知识产权保护,您将希望避免使用脚本。
如果您使用脚本,
你只需要从一些结构开始。 这里有一些可以帮助您入门的内容。
CustomAction 的 Javascript“样板”代码:
然后,使用如下内容注册自定义操作:
当然,您可以为多个自定义操作插入任意数量的 Javascript 函数。 一个例子:我使用 Javascript 在 IIS 上执行 WMI 查询,以获取可以安装 ISAPI 过滤器的现有网站列表。 然后,该列表用于填充稍后在 UI 序列中显示的列表框。 一切都很容易。
在 IIS7 上,IIS 没有 WMI 提供程序,因此我使用
shell.Run()
方法来调用 appcmd.exe 来执行工作。 简单的。相关问题:关于 Javascript CustomActions
Use Javascript CustomActions because they're soooo easy
People have said that Javascript is the wrong thing to use for MSI CustomActions. Reasons given: hard to debug, hard to make it reliable. I don't agree. It's not hard to debug, certainly no harder than C++. Its just different. I found writing CustomActions in Javascript to be super easy, much easier than using C++. Much faster. And just as reliable.
There's just one drawback: Javascript CustomActions can be extracted via Orca, whereas a C/C++ CA would require reverse-engineering. If you consider your installer magic to be protected intellectual property, you will want to avoid script.
If you use script,
you just need to start with some structure. Here's some to get you started.
Javascript "boilerplate" code for CustomAction:
Then, register the custom action with something like this:
You can, of course, insert as many Javascript functions as you like, for multiple custom actions. One example: I used Javascript to do a WMI query on IIS, to get a list of existing websites, to which an ISAPI filter could be installed. This list was then used to populate a listbox shown later in the UI sequence. All very easy.
On IIS7, there is no WMI provider for IIS, so I used the
shell.Run()
approach to invoke appcmd.exe to perform the work. Easy.Related question: About Javascript CustomActions
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 文件未“拉入”的任何片段。
Peter Tate has already shown how you can define reusable ComponentGroup definitions in separate wix fragments. Some additional tricks related to this:
Directory Aliasing
The component group fragments don't need to know about directories defined by the main product wxs. In your component group fragment you can talk about a folder like this:
Then the main product can alias one of its directories (e.g. "productInstallFolder") like this:
Dependency Graph
ComponentGroup elements can contain ComponentGroupRef child elements. This is great if you have a big pool of reusable components with a complex dependency graph between them. You just set up a ComponentGroup in its own fragment for each component and declare the dependencies like this:
If you now reference component group "B" in your setup because it is a direct dependency of your application, it will automatically pull in component group "A" even if the application author never realized that it was a dependency of "B". It "just works" as long as you don't have any circular dependencies.
Reusable wixlib
The above dependency graph idea works best if you compile the big-pool-o-reusable-components into a reusable wixlib with lit.exe. When creating an application setup, you can reference this wixlib much like a wixobj file. The candle.exe linker will automatically eliminate any fragments that are not "pulled in" by the main product wxs file(s).
我很惊讶没有人提到在构建过程中使用 T4 生成 WXS 文件。 我通过 Henry Lee @ 新时代解决方案。
本质上,您创建一个自定义 MSBuild 任务来执行 T4 模板,并且该模板在编译 Wix 项目之前输出 WXS。 这允许您(取决于您实现它的方式)自动包含编译另一个解决方案的所有程序集输出(这意味着您不再需要在每次添加新程序集时编辑 wxs)。
I'm surprised no one has mentioned using T4 to generate the WXS file during build. I learned about this by way of Henry Lee @ New Age Solutions.
Essentially, you create a custom MSBuild task to execute a T4 template, and that template outputs the WXS just before the Wix project is compiled. This allows you to (depending on how you implement it) automatically include all assemblies output from compiling another solution (meaning that you no longer have to edit the wxs ever time you add a new assembly).
使用 Heat.exe 砸脸并在令人痛苦的大型安装中造成“Epic Pwnage”
扩展 Si 和
Robert-P 关于热量的回答。
翻译:
(使用 heat 来避免手动将单个文件输入到项目中,并实现自动化构建,从而使整个过程变得更容易。)
WiX 2.0 Heat 语法详细信息
对于较新的版本(与旧版本并没有什么不同,但可能存在令人讨厌的语法更改...),请从 cmd.exe 转到 Heat 所在目录,然后输入 heat,但我这里有一个示例以寻求帮助如果需要,可以使用较新的版本。
将以下内容添加到 Visual Studio 2010 中的构建事件中。
(右键单击项目->属性->构建事件->预构建事件)
<代码>
$(WIX)bin\heat.exe" dir "$(EnviromentVariable)" -cg GroupVariable -gg -scom -sreg -sfrag -
srd -dr 安装 -var env.LogicPath -out "$(FragmentDir)\FileName.wxs
Heat 运行时生成指南(如执行上面的命令时)
不要抓取“COM 文件”
不要抓取“注册表文件”
不要抓取“片段”
不要抓取“根目录”
dir 表示您希望 Heat 查看在文件夹中
您要添加到(右键单击项目,转到属性)项目属性 -> 构建部分中的预处理器变量的变量名称,其中显示“定义预处理器变量”(假设为 Visual Studio 2010)
No double quotes but end with a semicolon
将从创建的片段引用到主 wxs 文件的 ComponentGroup
将存储输出 wxs 片段的片段目录 文件
的名称
完整教程在这里,非常有用
第 1 部分
第 2 部分
Using Heat.exe to smash face and inflict "Epic Pwnage" on painfully large installs
Expanding on Si's and
Robert-P's answers about heat.
Translation:
(Using heat to avoid typing individual files into the project by hand and for automating builds for an overall easier process.)
WiX 2.0 Heat Syntax detailed
For newer versions (not all that different from older versions but there are potentially annoying syntax changes....) go to the directory Heat is in from the cmd.exe and just type in heat but I have a example one right here for help with newer versions if needed.
Adding the following to your Build Event in visual studio 2010.
(Right Click Project->Properties ->Build Events-> Pre-Build Events)
$(WIX)bin\heat.exe" dir "$(EnviromentVariable)" -cg GroupVariable -gg -scom -sreg -sfrag -
srd -dr INSTALLLOCATION -var env.LogicPath -out "$(FragmentDir)\FileName.wxs
Generates Guids when heat is run(as in when you execute the command above)
Dont grab "COM files"
Dont grab "Registry Files"
Dont grab "Fragments"
Dont grab the "root Dir"
dir indicates you want Heat to look in a folder
The name of the variable you would add to the Preprocessor variables in the (Right click project, Go to properties) project properties->Build section where it says Define preprocessor variables (assumes visual studio 2010)
No double quotes but end with a semicolon
The ComponentGroup that will be referenced from the fragment created to the main wxs file
The fragment directory where the output wxs fragment will be stored
The the name of the file
Full tutorial here, So freakin helpful
Part 1
Part 2
包括 COM 对象:
heat
生成所有大多数(如果不是全部)注册表项以及它们所需的其他配置。 麾!包含托管 COM 对象(又名.NET 或 C# COM 对象)
在托管 COM 对象上使用
heat
将为您提供一个几乎完整的 wix 文档。如果您不需要 GAC 中可用的库(即全局可用:大多数情况下您的 .NET 程序集不需要此库 - 如果不打算这样做,您此时可能做错了什么共享库),您需要确保将
CodeBase
注册表项更新为[#ComponentName]
。 如果您计划将其安装到 GAC(例如,您已经制作了一些新的很棒的通用库,每个人都想使用),则必须删除此条目,并向File
添加两个新属性元素:Assembly
和KeyPath
。 Assembly 应设置为“.net”,KeyPath
应设置为“yes”。但是,某些环境(尤其是任何具有托管内存的环境,例如脚本语言)也需要访问 Typelib。 确保在您的类型库上运行
heat
并包含它。heat
将生成所有需要的注册表项。 多么酷啊?Including COM Objects:
heat
generates all most (if not all) the registry entries and other configuration needed for them. Rejoice!Including Managed COM Objects (aka, .NET or C# COM objects)
Using
heat
on a managed COM object will give you an almost complete wix document.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 theFile
element:Assembly
andKeyPath
. Assembly should be set to ".net" andKeyPath
should be set to "yes".However, some environments (especially anything with managed memory such as scripting languages) will need access to the Typelib as well. Make sure to run
heat
on your typelib and include it.heat
will generate all the needed registry keys. How cool is that?安装到
C:\ProductName
某些应用程序需要安装到
C:\ProductName
或类似的位置,但 99.9%(如果不是 100%) )网络安装中的示例到C:\Program Files\CompanyName\ProductName
。以下代码可用于将
TARGETDIR
属性设置为C:
驱动器的根目录(取自 WiX 用户列表):注意: 默认情况下,
TARGETDIR
不指向C:\
! 它指向ROOTDRIVE
,而 ROOTDRIVE 又指向具有最多可用空间的驱动器的根目录 (参见此处) - 这不一定是C:
驱动器。 可能还有另一个硬盘、分区或 USB 驱动器!然后,在
标记下方的某个位置,您像往常一样需要以下目录标记:Installing to
C:\ProductName
Some applications need to be installed to
C:\ProductName
or something similar, but 99.9% (if not 100%) of the examples in the net install toC:\Program Files\CompanyName\ProductName
.The following code can be used to set the
TARGETDIR
property to the root of theC:
drive (taken from the WiX-users list):NOTE: By default,
TARGETDIR
does not point toC:\
! It rather points toROOTDRIVE
which in turn points to the root of the drive with the most free space (see here) - and this is not necessarily theC:
drive. There might be another hard drive, partition, or USB drive!Then, somewhere below your
<Product ...>
tag, you need the following directory tags as usual:环境变量
将 Wxs 文档编译为 wixobj 代码时,您可以利用环境变量来确定各种信息。 例如,假设您想要更改项目中包含的文件。 假设您有一个名为 RELEASE_MODE 的环境变量,您在构建 MSI 之前设置了该变量(无论是使用脚本还是手动,都没关系)在您的 wix 源中,您可以执行以下操作:
然后在代码中执行 以下操作,使用它来动态更改您的 wxs 文档,例如:
Environmental Variables
When compiling your Wxs documents to wixobj code, you can make use of environmental variables to determine various information. For example, lets say you want to change which files get included in a project. Lets say you have an environmental variable called RELEASE_MODE, that you set right before you build your MSI (either with a script or manually, it doesn't matter) In your wix source, you can do something like:
and then later in your code, use it in place to on the fly change your wxs document, eg:
使用 RobM 特殊的“记住属性”模式
http://robmensching.com/blog/posts/2010/5/2/The-WiX-toolsets-Remember-Property-pattern
Using the RobM special "Remember Property" pattern
http://robmensching.com/blog/posts/2010/5/2/The-WiX-toolsets-Remember-Property-pattern
为使用托管代码 (C#) 编写的 WIX 创建自定义操作,无需投票
http://www.codeproject.com/KB/安装/wixcustomaction.aspx
Creating Custom Action for WIX written in managed code (C#) without Votive
http://www.codeproject.com/KB/install/wixcustomaction.aspx
编辑对话框
编辑对话框的一项良好功能是在版本 4.0.1.7090(或更高版本)中使用 SharpDevelop。 借助此工具,可以在设计视图中打开、预览和编辑独立对话框(来自 WiX 源的 wxs 文件,例如 InstallDirDlg.wxs)。
Editing Dialogs
One good ability to edit dialogs is using SharpDevelop in a version 4.0.1.7090 (or higher). With help of this tool a standalone dialog (wxs files from WiX sources like e.g. InstallDirDlg.wxs) can be opened, previewed and edited in Design view.
设置 IIS enable32BitAppOnWin64 标志 http://trycatchfail.com/blog/post/ WiX-Snippet-change-enable32BitAppOnWin64.aspx
Setting the IIS enable32BitAppOnWin64 flag http://trycatchfail.com/blog/post/WiX-Snippet-change-enable32BitAppOnWin64.aspx
修改“准备好安装了吗?” 对话框(又名VerifyReadyDlg)提供所做选择的摘要。
它看起来像这样:
替代文本 http://i46.tinypic.com/s4th7t.jpg
使用 Javascript 执行此操作CustomAction:
Javascript 代码:
声明 Javascript CA:
将 CA 附加到按钮。 在此示例中,当从CustomizeDlg单击“下一步”时,将触发CA:
相关SO问题:如何在运行时将文本设置为在VerifyReadyDlg中显示?
Modify the "Ready to install?" dialog (aka VerifyReadyDlg) to provide a summary of choices made.
It looks like this:
alt text http://i46.tinypic.com/s4th7t.jpg
Do this with a Javascript CustomAction:
Javascript code:
Declare the Javascript CA:
Attach the CA to a button. In this example, the CA is fired when Next is clicked from the CustomizeDlg:
Related SO Question: How can I set, at runtime, the text to be displayed in VerifyReadyDlg?
将可以单独修补的组件放入自己的片段中
它适用于制作产品安装程序和补丁,如果您在片段中包含任何组件,则必须包含所有该片段中的组件。 在构建安装程序的情况下,如果您错过任何组件引用,您将收到来自 light.exe 的链接错误。 但是,当您制作补丁时,如果您在片段中包含单个组件引用,那么该片段中所有更改的组件都将显示在您的补丁中。
像这样:
而不是这样:
另外,当使用 WiX.chm 帮助文件中的“Using Purely WiX”主题进行修补时,使用此过程生成补丁:
仅构建 1.1 版本的 Product.wixpdb 是不够的在单独的片段中使用组件。 因此,请务必在发货前正确分割您的产品。
Put Components which may be patched individually inside their own Fragments
It goes for both making product installers and patches that if you include any component in a fragment, you must include all of the components in that fragment. In the case of building an installer, if you miss any component references, you'll get a linking error from light.exe. However, when you make a patch, if you include a single component reference in a fragment, then all changed components from that fragment will show up in your patch.
like this:
instead of this:
Also, when patching using the "Using Purely WiX" topic from the WiX.chm help file, using this procedure to generate the patch:
it's not enough to just have the 1.1 version of the product.wixpdb built using the components in separate fragments. So be sure to correctly fragment your product before shipping.
从Wix3.0及更高版本打印EULA
1) 当您编译wix源代码时,light.exe必须在命令行中引用WixUIExtension.dll。 为此,请使用命令行开关 -ext。
2) 如果添加对 WixUIExtension.dll 的引用时,您的项目无法编译,这很可能是因为对话框 ID 冲突,即您的项目使用与 WixUIExtension.dll 中的某些标准对话框相同的对话框 ID,为您的对话框提供不同的 ID。 这是一个很常见的问题。
3) 您的许可证对话框必须具有 ID 为“LicenseText”的 ScrollableText 控件。 Wix 在打印时精确搜索该控件名称。
和一个引用自定义操作的 PushButton
4) 使用 Id="PrintEula" 定义 CustomAction,如下所示:
注意:与 Wix2.0 相比,Wix3.0 中的 BinaryKey 有所不同,并且必须完全是“WixUIWixca”(区分大小写)。
当用户按下按钮时,他/她将看到标准的选择打印机对话框,并且能够从那里进行打印。
Printing EULA from Wix3.0 and later
1) When you compile your wix source code, the light.exe must reference the WixUIExtension.dll in command line. Use the command line switch -ext for this.
2) If when you add the reference to the WixUIExtension.dll, your project fails to compile, this is most likely because of clashes of Dialog IDs, i.e. your project was using the same IDs of dialogs as some standard dialogs in WixUIExtension.dll, give different IDs to your dialogs. This is quite common problem.
3) Your license dialog must have ScrollableText control with the id "LicenseText". Wix searches for exactly this name of control when it prints.
and a PushButton which refers to the custom action
4) Define CustomAction with the Id="PrintEula" like this:
Note: BinaryKey is different in Wix3.0 comparing to Wix2.0 and must be exactly "WixUIWixca" (case sensitive).
When user presses the button he/she will be presented with the standard Select Printer Dialog and will be able to print from there.
我们在 GUI 第一个屏幕的某个位置(很小)显示产品版本。 因为人们每次选择正确的版本时都容易犯错误。 (并且让我们开发人员搜索了很长时间......)
我们已经设置了 TFSBuild,还可以使用不同环境的配置生成转换(.mst 文件)。 (我们了解需要部署到的所有环境)。
由于 Grant Holliday 的原始博客文章已关闭,我将其内容复制粘贴到此处:
MSBuild 任务从 XML 生成 MSI 转换文件 2008 年 3 月 11 日
在我的上一篇文章中,我描述了如何使用 MSI 转换 (*.mst) 文件来分离环境- 来自通用 MSI 包的特定配置设置。
尽管这为您的配置提供了一定程度的灵活性,但转换文件有两个缺点:
幸运的是,我们可以使用 Microsoft Windows Installer 对象库 (c:windowssystem32msi.dll) 打开 MSI“数据库”并创建转换文件。
积分再次转到Alex Shevchuk – 从 MSI 到 WiX – 第 7 部分 – 使用 Transforms 自定义安装,向我们展示如何使用 VbScript 实现这一目标。 本质上,我所做的只是采用 Alex 的示例,并使用 Interop.WindowsInstaller.dll 实现了 MSBuild 任务。
MSBuild 任务
下载< /a> 源代码 & 这里有transforms.xml 示例(~7Kb 压缩的 VS2008 解决方案)
We display the product version somewhere (tiny) in the first screen of the GUI. Because people tend to make mistakes in picking the right version every time. (And keep us developers searching for ages..)
We've set up TFSBuild to also generate transforms (.mst files) with the configuration for our different environments. (We know about all environments we need to deploy to).
Since the original weblog post by Grant Holliday is down, I copy pasted its contents here:
MSBuild task to generate MSI Transform files from XMLMarch 11 2008
In my previous post I described how you can use MSI Transform (*.mst) files to separate environment-specific configuration settings from a generic MSI package.
Although this provides a level of flexibility in your configuration, there are two down-sides of Transform files:
Fortunately we can use the Microsoft Windows Installer Object Library (c:windowssystem32msi.dll) to open MSI “databases” and create transform files.
Credits go again to Alex Shevchuk – From MSI to WiX – Part 7 – Customising installation using Transforms for showing us how to achieve this with VbScript. Essentially all I’ve done is taken Alex’s example and using Interop.WindowsInstaller.dll I’ve implemented an MSBuild task.
The MSBuild Task
Download the source code & example transforms.xml here (~7Kb Zipped VS2008 Solution)
在部署安装包之前,我总是控制它的内容。
这只是在命令行上进行一个简单的调用(根据 Terrences 帖子)打开命令行并输入
这会将包内容提取到当前路径的子目录“Extract”中。
Before deploying an install package I always control the content of it.
It's just a simple call at the command line (according to Terrences post) open command line and enter
This will extract package contents to an subdir 'Extract' with the current path.
使用 InstEd 代替 ORCA,这是查看 MSI 表的好工具。 它还能够通过以下方式区分两个包
变换-> 比较...
此外,还提供具有附加功能的 Plus 版本。 而且免费版本也为 Orca 提供了一个很好的替代方案。
Instead of ORCA use InstEd which is a good tool for viewing MSI tables. Also it has the ability to diff two packages by
Transform -> Compare To...
Additionally a Plus version with additional functionality is available. But also the free version offers a good alternative for Orca.
为具有 x86/x64 兼容性的 COM Interop 注册 .NET 程序集
注意此片段本质上与 REGASM Assembly.dll /codebase 相同
本示例中发生了一些事情所以这是代码,稍后我会解释它...
如果您想知道,这实际上是针对 ASCOM 望远镜驱动程序。
首先,我采纳了上面的建议,并在一个单独的文件中创建了一些 platforma 变量,您可以看到这些变量分散在 XML 中。
顶部附近的 if-then-else 部分处理 x86 与 x64 兼容性。 我的程序集面向“任何 CPU”,因此在 x64 系统上,我需要将其注册两次,一次在 64 位注册表中,一次在 32 位
Wow6432Node
区域中。 if-then-else 对此进行了设置,这些值稍后将在foreach
循环中使用。 这样,我只需编写一次注册表项(DRY 原则)。file 元素指定正在安装和注册的实际程序集 dll:
没有什么革命性的,但请注意
Assembly=".net"
- 仅此属性就会导致程序集被放入 GAC 中,这不是我想要什么。 使用AssemblyApplication
属性指向自身只是阻止 Wix 将文件放入 GAC 的一种方法。 现在,Wix 知道它是一个 .net 程序集,它允许我在 XML 中使用某些绑定器变量,例如!(bind. assemblyFullname.filDriverAssembly)
来获取程序集全名。Registering .NET assemblies for COM Interop with x86/x64 compatibility
NB This fragment is essentially the same as REGASM Assembly.dll /codebase
A couple of things are going on in this sample so here's the code and I'll explain it afterwards...
If you were wondering, this is actually for an ASCOM Telescope Driver.
First, I took advice from above and created some platforma variables in a seperate file, you can see those scattered through the XML.
The if-then-else part near the top deals with x86 vs x64 compatibility. My assembly targets 'Any CPU' so on an x64 system, I need to register it twice, once in the 64-bit registry and once in the 32-bit
Wow6432Node
areas. The if-then-else sets me up for this, the values are used in aforeach
loop later on. This way, I only have to author the registry keys once (DRY principle).The file element specifies the actual assembly dll being installed and registered:
Nothing revolutionary, but notice the
Assembly=".net"
- this attribute alone would cause the assembly to be put into the GAC, which is NOT what I wanted. Using theAssemblyApplication
attribute to point back to itself is simply a way of stopping Wix putting the file into the GAC. Now that Wix knows it's a .net assembly, though, it lets me use certain binder variables within my XML, such as the!(bind.assemblyFullname.filDriverAssembly)
to get the assembly full name.设置 DISABLEADVTSHORTCUTS 属性可强制安装程序中所有公布的快捷方式成为常规快捷方式,并且您无需包含用作键路径的虚拟注册表键。
我认为 Windows Installer 4.0 或更高版本是要求< /a>.
Set the
DISABLEADVTSHORTCUTS
property to force all advertised shortcuts in your installer to become regular shortcuts, and you don't need to include a dummy reg key to be used as the keypath.I think Windows Installer 4.0 or higher is a requirement.
这是一个很好的结构,但根据我的经验,我想知道您如何解决这些情况:
A. 您的安装似乎都落在同一个目的地。 如果用户需要一次安装所有 3 个版本,您的流程是否允许这样做。 他们能否清楚地知道他们正在触发的每个可执行文件的版本?
B. 如何处理 TEST 和/或 TRAINING 中存在但 LIVE 中尚未存在的新文件?
It's a nice structure but based on my experience I wonder how you address these conditions:
A. Your installs all appear to land in the same destination. If a user needs to install all 3 versions at once will your process allow this. Can they unambiguously tell which version of every executable they are triggering?
B. How do you handle new files that exist in TEST and/or TRAINING but not yet in LIVE?
这里是一种帮助大型 Web 项目的方法验证部署的文件数量是否与 MSI(或合并模块)中内置的文件数量匹配。 我刚刚针对我们的主应用程序(仍在开发中)运行了自定义 MSBuild 任务,它发现了相当多丢失的文件,大部分是图像,但有一些 javascript 文件已经漏掉了!
这种方法(通过连接到 WiX 项目的 AfterBuild 目标来查看 MSI 的文件表)可以适用于您可以访问预期文件的完整列表的其他应用程序类型。
Here's a way to help large web projects verify that the number of deployed files matches the number of files built into an MSI (or merge module). I've just run the custom MSBuild task against our main application (still in development) and it picked up quite a few missing files, mostly images, but a few javascript files had slipped through to!
This approach (peeking into File table of MSI by hooking into AfterBuild target of WiX project) could work for other application types where you have access to a complete list of expected files.
当安装不允许卸载或重新安装并且不回滚时执行强制重新安装。
VBscript 脚本用于覆盖因任何原因而未卸载的安装。
Performing a forced reinstall when an install doesn't allow uninstall or reinstall and doesn't roll back.
VBscript script used for overriding an install that isn't uninstalling for whatever reason..
创建一个具有自定义操作的 UI,该操作将设置一个变量,并且 UI 将根据自定义操作中设置的变量禁用/启用下一个按钮(或类似按钮)。
并不像您想象的那么简单,也不是太难,只是没有在任何地方记录!
Wix 与条件、属性和属性的交互 自定义操作
Create a UI that has a custom action that will set a variable and the UI will disable/enable the next button (or similar) based upon the variable set in the custom action.
Not as straight-forward as you would think, not too difficult just not documented anywhere!
Wix Interactions with Conditions, Properties & Custom Actions
将变量保存在单独的
wxi
包含文件中。 允许重用,可以更快地查找变量,并且(如果需要)可以更轻松地通过外部工具进行操作。为 x86 和 x64 版本定义平台变量
将安装位置存储在注册表中,以便升级能够找到正确的位置。 例如,如果用户设置自定义安装目录。
注意:WiX 大师 Rob Mensching 发布了 优秀的博客条目,其中详细介绍了修复了从命令行设置属性时的边缘情况。
使用 1. 2. 和 3. 的示例
和
最简单的方法始终是 主要升级,因为它允许在单个 MSI 中进行新安装和升级。 UpgradeCode 固定为唯一的 Guid 并且永远不会改变,除非我们不想升级现有产品。
注意:在 WiX 3.5 中,有一个新的 MajorUpgrade 元素使生活均匀更容易!
在“添加/删除程序”中创建图标
在发布版本中,我们对安装程序进行版本控制,将 msi 文件复制到部署目录。 使用从 AfterBuild 目标调用的 wixproj 目标的示例:
使用 heat 获取带有通配符 (*) Guid 的文件。 如果您想在多个项目中重用 WXS 文件,这很有用(请参阅我对同一产品的多个版本的回答)。 例如,此批处理文件自动收集 RoboHelp 输出。
发生了一些事情,
robocopy
正在收集之前剥离 Subversion 工作副本元数据;-dr
根目录引用设置为我们的安装位置而不是默认的 TARGETDIR;-var
用于创建一个变量来指定源目录(Web 部署输出)。通过使用 Strings.wxl 进行本地化,可以轻松地将产品版本包含在欢迎对话框标题中。 (来源:saschabeaumont。添加是因为这个很棒的提示隐藏在评论中)
为自己省去一些麻烦,然后按照< a href="https://stackoverflow.com/questions/1602831/wix-one-file-per-component-or-several-files-per-component/1604348#1604348">Wim Coehen 的建议之一每个文件的组件。 这还允许您省略(或通配符
*
)组件 GUID。Rob Mensching 有一个 通过搜索
值 3
快速追踪 MSI 日志文件中问题的巧妙方法。 请注意有关国际化的评论。添加条件功能时,更直观的做法是将默认功能级别设置为 0(禁用),然后将条件级别设置为所需的值。 如果您设置默认功能级别 >= 1,则条件级别必须为 0 才能禁用它,这意味着条件逻辑必须与您期望的相反,这可能会令人困惑:)
Keep variables in a separate
wxi
include file. Enables re-use, variables are faster to find and (if needed) allows for easier manipulation by an external tool.Define Platform variables for x86 and x64 builds
Store the installation location in the registry, enabling upgrades to find the correct location. For example, if a user sets custom install directory.
Note: WiX guru Rob Mensching has posted an excellent blog entry which goes into more detail and fixes an edge case when properties are set from the command line.
Examples using 1. 2. and 3.
and
The simplest approach is always do major upgrades, since it allows both new installs and upgrades in the single MSI. UpgradeCode is fixed to a unique Guid and will never change, unless we don't want to upgrade existing product.
Note: In WiX 3.5 there is a new MajorUpgrade element which makes life even easier!
Creating an icon in Add/Remove Programs
On release builds we version our installers, copying the msi file to a deployment directory. An example of this using a wixproj target called from AfterBuild target:
Use heat to harvest files with wildcard (*) Guid. Useful if you want to reuse WXS files across multiple projects (see my answer on multiple versions of the same product). For example, this batch file automatically harvests RoboHelp output.
There's a bit going on,
robocopy
is stripping out Subversion working copy metadata before harvesting; the-dr
root directory reference is set to our installation location rather than default TARGETDIR;-var
is used to create a variable to specify the source directory (web deployment output).Easy way to include the product version in the welcome dialog title by using Strings.wxl for localization. (Credit: saschabeaumont. Added as this great tip is hidden in a comment)
Save yourself some pain and follow Wim Coehen's advice of one component per file. This also allows you to leave out (or wild-card
*
) the component GUID.Rob Mensching has a neat way to quickly track down problems in MSI log files by searching for
value 3
. Note the comments regarding internationalization.When adding conditional features, it's more intuitive to set the default feature level to 0 (disabled) and then set the condition level to your desired value. If you set the default feature level >= 1, the condition level has to be 0 to disable it, meaning the condition logic has to be the opposite to what you'd expect, which can be confusing :)
检查是否安装了 IIS:
检查 Vista+ 上是否安装了 IIS 6 元数据库兼容性:
Checking if IIS is installed:
Checking if IIS 6 Metabase Compatibility is installed on Vista+:
将所有 ID 保留在单独的命名空间中
F 开头的功能。
示例:F.Documentation、F.Binaries、F.SampleCode。C 开头。
例如:C.ChmFile、C.ReleaseNotes、C.LicenseFile、C.IniFile、C.RegistryCA。
例如:CA.LaunchHelp、 CA.UpdateReadyDlg、CA.SetPropertyXFi.
Di.
我发现这对于跟踪所有不同类别中的所有不同 ID 有很大帮助。
Keep all IDs in separate namespaces
F.
Examples: F.Documentation, F.Binaries, F.SampleCode.C.
Ex: C.ChmFile, C.ReleaseNotes, C.LicenseFile, C.IniFile, C.RegistryCA.
Ex: CA.LaunchHelp, CA.UpdateReadyDlg, CA.SetPropertyXFi.
Di.
I find this helps immensely in keeping track of all the various id's in all the various categories.
很棒的问题。 我很乐意看到一些最佳实践。
我有很多要分发的文件,因此我将项目设置为几个 wxs 源文件。
我有一个顶级源文件,我称之为 Product.wxs,它基本上包含安装的结构,但不包含实际的组件。 该文件有几个部分:
.wix 文件的其余部分由包含 ComponentGroups 的片段组成,这些组件组在 Product.wxs 的功能标记中引用。 我的项目包含我分发的文件的良好逻辑分组
这并不完美,我的 OO 蜘蛛感觉有点刺痛,因为片段必须引用 Product.wxs 文件中的名称(例如 DirectoryRef),但我发现更容易维护一个大的源文件。
我很想听到对此的评论,或者是否有人也有任何好的建议!
Fantastic question. I'd love to see some best practices shown.
I've got a lot of files that I distribute, so I've set up my project into several wxs source files.
I have a top level source file which I call Product.wxs which basically contains the structure for the installation, but not the actual components. This file has several sections:
The rest of the .wix files are composed of Fragments that contain ComponentGroups which are referenced in the Feature tag in the Product.wxs. My project contains a nice logical grouping of the files that I distribute
This isn't perfect, my OO spider sense tingles a bit because the fragments have to reference names in the Product.wxs file (e.g. the DirectoryRef) but I find it easier to maintain that a single large source file.
I'd love to hear comments on this, or if anyone has any good tips too!
在退出对话框中添加一个复选框以启动应用程序或帮助文件。
...
如果这样做,“标准”外观就不太正确。 复选框始终为灰色背景,而对话框为白色:
替代文本 http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_1.gif
一种方法围绕这个问题是指定您自己的自定义ExitDialog,具有不同位置的复选框。 这可行,但似乎只是为了改变一个控件的颜色就需要做很多工作。 解决同一问题的另一种方法是对生成的 MSI 进行后处理,以更改该特定 CheckBox 控件的控制表中的 X、Y 字段。 javascript 代码如下所示:
在生成 MSI(从 light.exe)后,将这段代码作为命令行脚本运行(使用 cscript.exe)将产生一个看起来更专业的 ExitDialog:
替代文本 http://www.dizzymonkeydesign.com/blog /misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_2.gif
Add a checkbox to the exit dialog to launch the app, or the helpfile.
...
If you do it this way, the "standard" appearance isn't quite right. The checkbox is always a gray background, while the dialog is white:
alt text http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_1.gif
One way around this is to specify your own custom ExitDialog, with a differently-located checkbox. This works, but seems like a lot of work just to change the color of one control. Another way to solve the same thing is to post-process the generated MSI to change the X,Y fields in the Control table for that particular CheckBox control. The javascript code looks like this:
Running this code as a command-line script (using cscript.exe) after the MSI is generated (from light.exe) will produce an ExitDialog that looks more professional:
alt text http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_2.gif
使用相同的源文件创建实时、测试、培训等版本。
简而言之:为每个安装程序创建唯一的 UpgradeCode,并自动为每个安装程序定义每个 Guid 的第一个字符,其余 31 个字符保持唯一。
先决条件
假设
目录结构
处理
Example Config.wxi
Example Config.Common.wxi
Example Components.wxs
注意:我现在建议将 Guid 属性保留在 Component 之外(相当于
*
),每个组件使用一个文件并将该文件设置为密钥路径。 这样就无需调用如下所示的ModifyComponentsGuids
和RevertComponentsGuids
目标。 但这可能不适用于您的所有组件。示例Setup.Live.wixproj
最终想法
更新1: 自动生成组件指南 如果您为每个文件创建带有 Guid="*" 的组件,并将文件设置为键路径,则无需调用 FileUpdate 任务。
更新2:我们遇到的问题之一是,如果您不自动生成组件Guid并且构建失败,则需要手动删除临时文件。更新3:找到了一种方法来消除对 svn:externals 和临时文件创建的依赖。 这使得构建过程更有弹性(如果你不能使用通配符你的指南,这是最好的选择),并且如果在灯光或蜡烛下发生构建失败,那么脆弱性更小。
更新4:支持
Creating Live, Test, Training, ... versions using the same source files.
In a nutshell: Create unique UpgradeCode for each installer and automagically define the first character of each Guid for each installer, leaving the remaining 31 unique.
Prerequisites
Assumptions
Directory Structure
Process
Example Config.wxi
Example Config.Common.wxi
Example Components.wxs
Note: I would now suggest leaving the Guid attribute out of Component (equivalent of
*
), using one file per component and setting the file as the keypath. This removes the need for callingModifyComponentsGuids
andRevertComponentsGuids
targets shown below. This might not be possible for all your components though.Example Setup.Live.wixproj
Final thoughts
UPDATE 1: Auto-generating component Guids removes the need for calling FileUpdate task if you create component with Guid="*" for each file, setting the file as the keypath.
UPDATE 2: One of the issues we've come up against is if you don't auto-generate your component Guid's and the build fails, then the temp files need to be manually deleted.UPDATE 3: Found a way to remove reliance on svn:externals and temporary file creation. This makes the build process more resilient (and is best option if you can't wildcard your Guids) and less brittle if there is a build failure in light or candle.
UPDATE 4: Support for Multiple Instances using instance transforms is in WiX 3.0+, definitely also worth a look.
使用 Msi 诊断日志记录获取详细的故障信息
<代码>
msiexec /i Package.msi /l*vc:\Package.log
在哪里
is the name of your package
and
is where you want the output of the log
Msi 错误代码
Wix 介绍视频
哦,Random Wix 的介绍视频“Mr. WiX”Rob Mensching 很有帮助。
Using the Msi Diagnostic logging to get detailed failure Information
msiexec /i Package.msi /l*v c:\Package.log
Where
is the name of your package
and
is where you want the output of the log
Msi Error Codes
Wix Intro Video
Oh and Random Wix intro video featuring "Mr. WiX" Rob Mensching is "conceptual big picture" helpful.