What is the correct syntax for giving guids for components in the wxs file for WIX?
In most samples I found
Guid="00AD2D6E-BF8A-4EA8-BE9A-57380DECD0E6"
but in some samples I found
Guid="{00AD2D6E-BF8A-4EA8-BE9A-57380DECD0E6}"
I would prefer the second version, because this is directly generated by the GuidGen tool. But is it correct?
Component GUIDs: On Component GUIDs and when they should change: Change my component GUID in wix?
Auto-guids and default attribute values
In addition to Bob Arnson's advice:
Recent versions of Wix allows GUIDs to be auto-generated for several things, most significantly component GUIDs. It also covers package-, product- and patch-codes.
It also allows skipping some, or even most attribute values from explicit definition since most of them can be defaulted to predictable values. See code snippet below for an example.
Auto generating component GUIDs is possible because component GUIDs should remain the same once created unless the installation path is changed - this is described in this stackoverflow post. Accordingly Wix calculates a GUID based on the target path and other factors.
Product, package and patch code can generally be randomly created as they are simply supposed to be unique.
Note that an upgrade code is special - it should not be auto generated. It is generally desired to remain stable between releases and even between different editions and languages of the software in some cases - this depends on application design and how editions are implemented (you can use different upgrade codes and still implement a major upgrade, but the upgrade table gets complicated).
As a rule of thumb upgrade code identifies a "family of related products", product code identifies an installed edition of some kind and package code identifies a unique file. Two files with the same package code is by definition treated as the same file (this can case mysterious errors - make sure to always auto-generate the package code).
Check the Wix documentation for details on the auto-generated GUIDs.
Simplified Wix XML Source Files
Used correctly these auto-generated GUIDs can significantly simplify your Wix source files:
<!-- Sample guid below, do not copy paste -->
<Component Id="File.dll" Guid="{12345678-1234-1234-1234-123456789ABC}">
<File Id="File.dll" Name="File.dll" KeyPath="yes" Source="..\File.dll" />
</Component>
versus
<Component>
<File Source="..\File.dll" />
</Component>
Taken together, the combination of auto-guids and the default attribute values yield Wix XML source files that are shorter and easier to read due to the removal of a lot of "noise" - this arguably makes them less error prone:
terser source files are easier to maintain and less error prone since it is easier to see what changes with diff tools and the less text exists, the less errors can hide
along the same lines, copy and paste of existing XML elements can cause difficult to find errors due to incomplete update of all attributes. Fewer attributes, fewer errors. I copy and paste a lot when using Wix "manually" (not using XML generators). Note that most errors are picked up by the Wix compiler and linker, but errors can still hide.
any changes to the default values can then be picked up auto-magically from the compiler and the linker making them propagate easier to MSI files everywhere that have been built with Wix. It is always good to keep your source files as simple as possible, but no simpler
overridden defaults also stand out in the source file, and you can add comments to explain why the non-default value is needed
Other Wix tips here, though the article may be a bit dated.
The WiX compiler converts either form to the form that Windows Installer expects (with braces and uppercase letters).
I've used both of them and both seem to work perfectly fine.
Related
I have many files (hundreds) in my project's output BIN folder. I simply need to have an installer to include the files in the bin folder in an MSI installer.
In my WIX installer project, I have the following target to use the harvest tool and generate a list of all files in a bin folder, later on, I reference them in my WIX definitions:
<Target Name="GenerateHeat">
<HeatDirectory Directory="..\MyApp\bin\Debug"
PreprocessorVariable="var.HeatPath" OutputFile="HarvestedFiles.wxs"
ComponentGroupName="HarvestedFiles" DirectoryRefId="FOLDER1"
AutogenerateGuids="true" ToolPath="$(WixToolPath)"
SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" />
</Target>
Is there any way to simply include all files in a bin folder and include them in the MSI without generating the intermediate file list? I prefer to specify the BIN folder name and WIX includes them in a <ComponentGroup>, so I can reference it in my <Product>
Update and clarification
This question is not about how MSI works. This is about how WIX can copy the content of a folder into an MSI without specifying every single file name in a <Component> and <File> sandwich.
Is there any way to simply include all files in a bin folder and
include them in the MSI without generating the intermediate file list?
This is not possible with built-in functionality of the free version of WiX. As Stein Åsmul points out, the commercial branch of WiX might have something like that.
If commercial WiX is not an option and you are ready to invest significant time in C# development, using mostly undocumented API, you could write a WiX compiler extension that adds entries to the File and Component tables based on a given source directory path. It could also generate component groups, that can be referenced elsewhere.
I have done exactly this in the past but it certainly wasn't a trivial task. One should also have very good knowledge of component rules and MSI in general before doing things like generating component GUIDs. You will find some pseudo code below. Before going down this route, it would be worth looking around if someone else has created an open-source WiX extension like that.
This is the kind of authoring that could be achieved with such a compiler extension:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:ex="MyExtensionUri">
<Product ... >
<Feature Id="ProductFeature" Title="MyFeature" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<ex:ComponentGroupFromFiles Id="ProductComponents"
Directory="INSTALLFOLDER"
Source="MyApp\bin"
Wildcard="*"/>
</Fragment>
</Wix>
Here is some pseudo code for a compiler extension. This is mainly intended to serve as keywords for exploring the WiX source "Compiler.cs".
Override Wix.CompilerExtension.ParseElement() to parse the attributes of your extension element.
Create component group and reference it by the product:
Wix.Row compGroupRow = Core.CreateRow(sourceLineNumbers, "WixComponentGroup");
compGroupRow[0] = myComponentGroupId;
Core.CreateWixGroupRow( sourceLineNumbers, Wix.ComplexReferenceParentType.Product, Core.ActiveSection.Id, Wix.ComplexReferenceChildType.ComponentGroup, myComponentGroupId );
For each component/file:
// Add record to the Component table
Wix.Row compRow = Core.CreateRow( sourceLineNumbers, "Component" );
// TODO: Assign data to compRow[0..5] according to MSI "Component" table documentation
// Add this component to the component group.
Core.CreateComplexReference( sourceLineNumbers, Wix.ComplexReferenceParentType.ComponentGroup, myComponentGroupId, "", Wix.ComplexReferenceChildType.Component, myComponentId, false );
// Add record to the File table.
Wix.Row fileRow = Core.CreateRow( sourceLineNumbers, "File" );
// TODO: Assign data to fileRow[0..2] and [6] according to MSI "File" table documentation. Columns 3, 4, 5, 7 are written by the WiX binder at a later time! Set them to null (if nullable) or 0.
// Create required metadata for WiX
Wix.WixFileRow wixFileRow = (Wix.WixFileRow) Core.CreateRow(sourceLineNumbers, "WixFile");
// TODO: Assign wixFileRow.File, wixFileRow.Directory, wixFileRow.DiskId, wixFileRow.Source
// Set wixFileRow.Attributes to 1 if you have generated a short file name.
// Add reference to the Media table
Core.CreateWixSimpleReferenceRow( sourceLineNumbers, "Media", diskId );
Useful utilities for generating Component / File table column data:
Core.GenerateIdentifier()
Core.GenerateShortName()
How to add components to a merge module? This is left as an exercise for the reader. 😉 Just find the code in WiX's "Compiler.cs".
FireGiant: I believe the commercial branch of WiX (FireGiant), has a module for this. HeatWave Harvesting - or something like that. It is part of the WiX expansion pack if I am not mistaken. It allows advanced harvesting to create MSI files and perhaps other formats that I am not aware of. I know next to nothing about the module apart from that. Oh, it also supports COM extraction from 64-bit COM files - which is not working in heat.exe at the moment.
Tallow: Back in the days of WiX2 there was a tool called Tallow that was developed by someone whose name I can not recall. It generated WiX markup to install files from a given input folder and even kept component GUIDs in sync (as far as I recall). I saw some copies of it on github.com, but the repository I downloaded had several malware hits, so no link.
Paraffin: A tool I have never used is Paraffin - supposedly a better Tallow - https://github.com/Wintellect/Paraffin. I can't say much about it since I have not tried it. Give it a quick look? I am not sure if it is maintained at all to be honest, but it sure beats rolling your own solution from scratch.
That would be against the whole design concept of Windows Installer.
Windows Installer manages the health/installation status of Components. It does this across all versions of all products that are installed. To make this workable, there are
"Components Rules." To make the rules manageable over component lifecycles, a component should be atomic: one file (or multi-file .NET assembly) and/or registry key.
(If you have a choice, you don't have to use Windows Installer if you don't appreciate its design.)
Also, you should consider whether, how and where whatever is in your bin folder should be installed. Its basic intent is for debugging in place. It may contain thing that 1) you aren't licensed to redistribute, 2) you are licensed to redistribute only in specific ways, 3) might already be part of the target systems, 4) might be best redistributed with their original installer from the vendor 5) you don't actually want to deliver to users, …. For these concerns, you can either narrow down the harvesting or filter out specific results.
Tip: If you want to modularize your installation, you could build sets of components into different MSI files and use WiX's bootstrapper to install them together.
Unless your talking about a web application / website (think node.js directory structure) I recommend against this.
For the some package manager authored all these thousands of files for me story (^^^) then use Heat.
For all the other normal scenarios I created IsWiX. It helps me reduce the complexity and friction of authoring/maintaining installers while keeping me in control of what does/doesn't ship and when something does or doesn't get installed (features).
https://iswix.com/2007/06/20/dealing-with-very-large-number-of-files/
https://github.com/iswix-llc/iswix-tutorials
I've been trying to set up a WiX component such that the user can specify that the installer should not upgrade that component on a MajorUpgrade. I had the following code, but this means that if the condition is met then the new version is not installed, but the old version is also removed.
<Component Id="ExampleComponent" GUID="{GUID here}">
<Condition>NOT(KEEPOLDFILE="TRUE")</Condition>
<File Id="ExampleFile" Name="File.txt" KeyPath="yes" Source="File.txt"/>
</Component>
Ideally, if the user specifies "KEEPOLDFILE=TRUE", then the existing version of "File.txt" should be kept. I've looked into using the Permanent attribute, but this doesn't look relevant.
Is this possible to achieve without using CustomActions?
A bit more background information would be useful, however:
If your major upgrade is sequenced early (e.g. afterInstallInitialize) the upgrade is an uninstall followed by a fresh install, so saving the file is a tricky proposition because you'd save it, then do the new install, then restore it.
If the upgrade is late, then file overwrite rules apply during the upgrade, therefore it won't be replaced anyway. You'd need to do something such as make the creation and modify timestamps identical so that Windows will overwrite it with the new one. The solution in this case would be to run a custom action conditioned on "keep old file", so you'd do the reverse of this:
https://blogs.msdn.microsoft.com/astebner/2013/05/23/updating-the-last-modified-time-to-prevent-windows-installer-from-updating-an-unversioned-file/
And it's also not clear if that file is ALWAYS updated, so if in fact it has not been updated then why bother to ask the client whether to keep it?
It might be simpler to ignore the Windows Installer behavior by setting its component id to null, as documented here:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa368007(v=vs.85).aspx
Then you can do what you want with the file. If you've already installed it with a component guid it's too late for this solution.
There are better solutions that require the app to get involved where you install a template version of this file. The app makes a copy of it that it always uses. At upgrade time that template file is always replaced, and when the app first runs after the upgrade it asks whether to use the new file (so it copies and overwrites the one it was using) or continue to use the existing file. In my opinion delegating these issues to the install is not often an optimal solution.
Setting attributes like Permanent is typically not a good idea because they are not project attributes you can turn on and off on a whim - they apply to that component id on the system, and permanent means permanent.
I tried to make this a comment, it became to long. I prefer option 4 that Phil describes. Data files should not be meddled with by the setup, but managed by your application exe (if there is one) during its launch sequence. I don't know about others, but I feel like a broken record repeating this advice, but hear us out...
There is a description of a way to manage your data file's overwriting or preservation here. Essentially you update your exe to be "aware" of how your data file should be managed - if it should be preserved or overwritten, and you can change this behavior per version of your application exe if you like. The linked thread describes registry keys, but the concept can be used for files as well.
So essentially:
Template: Install your file per-machine as a read-only template
Launch Sequence: Copy it in place with application.exe launch sequence magic
Complex File Revision: Update the logic for file overwrite or preservation for every release as you see fit along the lines as the linked thread proposes
Your setup will "never know" about your data file, only the template file. It will leave your data file alone in all cases. Only the template file it will deal with.
Liberating your data files from the setup has many advantages:
Setup.exe bugs: No unintended accidental file overwrites or file reset problems from problematic major upgrade etc... this is a very common problem with MSI.
Setup bugs are hard to reproduce and debug since the conditions found on the target systems can generally not be replicated and debugging involves a lot of unusual technical complexity.
This is not great - it is messy - but here is a list of common MSI problems: How do I avoid common design flaws in my WiX / MSI deployment solution? - "a best effort in the interest of helping sort of thing". Let's be honest, it is a mess, but maybe it is helpful.
Application.exe Bugs: Keep in mind that you can make new bugs in your application.exe file, so you can still see errors - obviously. Bad ones too - if you are not careful - but you can easily implement a backup feature as well - one that always runs in a predictable context.
You avoid the complicated sequencing, conditioning and impersonation concerns that make custom actions and modern setups so complicated to do right and make reliable.
Following from that and other, technical and practical reasons: it is much easier to debug problems in the application launch sequence than bugs in your setup.
You can easily set up test conditions and test them interactively. In other words you can re-create problem conditions easily and test them in seconds. It could take you hours to do so with a setup.
Error messages can be interactive and meaningful and be shown to the user.
QA people are more familiar with testing application functionality than setup functionality.
And I repeat it: you are always in the same impersonation context (user context) and you have no installation sequence to worry about.
I have a wix project file containing the following structure:
cultures
- en
- profile.mo
- de
- profile.mo
...
I'm creating several MSI files containing the localized MSI strings.
What I like to achive is that the files for "de" and other languages are included in the specific MSI files.
This will reduce the overall size of the setup a lot. Currently I'm using conditions based on localization:
<Component Id="compLangDePluginMo" Guid="{YOUR-GUID}" >
<Condition><![CDATA["!(loc.Localization)" = "de-de"]]></Condition>
<File Id="fLangDePluginMo" Name="plugin.mo" Source="$(var.ProjectRef.ProjectDir)catalogs\de\de.mo" />
</Component>
where in every WXL file there's a statement like
<String Overridable="yes" Id="Localization">en-us</String>
or
<String Overridable="yes" Id="Localization">de-de</String>
The drawback is that all MSI files contain all language specific files.
P.S. The MO file is just an example. We are taking about several MB of language specific files, therefore there's no chance to just have the messages included in transformations.
You can't have components in transforms (because files would need to go in the File table, in a CAB and so on).
If you have one neutral MSI file that means you'd have a bundle per language, the neutral MSI with the functionality and the language specific one. So you could have a WiX bundle/bootstrapper per language: the neutral MSI plus one language.
Why did you choose conditional components? There are situations where users can change those conditions and a repair would alter the installed state of the components (and sometimes that's a feature not a bug). Languages as Features could be a bit more predictable.
Also one separate MSI for all the language specific data can be useful so that functionality can change but the language MSI doesn't need rebuilding - doesn't reduce size though, which seems to be the issue.
One other note: sometimes qualified components are used to provide this functionality, where for example the app can use MsiProvideQualifiedComponentEx to install the appropriate language files, but I'm not sure that it would help in your case if your product is not multi-language (but it is single language).
If you're thinking about transforms you may as well go the whole way and look at patches. You could have the base MSI with no languages and another "identical" MSI that contains (for example) the de-de changes ( as long as you are careful with the components) and then ship the base MSI with a patch per language, applying the patch according to the system. A bundle could apply the base plus the appropriate patch. Also a patch can be applied to an administrative install, so you'd then have an installable image but with loose files, if that's acceptable.
Chris makes an interesting point about transforms adding loose external files, but it's not clear (at least to me) if it's actually possible given the changes required to the base MSI (marking mixed files, dealing with file hashes and so on).
I am someone with little to no experience with wix and I am trying to support Windows also for the component I am responsible for. I am trying to create merge module for a set of files that my product generates. These files exist in numerous sub directories. I was wondering how I can create a single component ID for all the files in the entire tree. I am not worried about minor upgrades as that is something I am not going to be doing. I am trying to avoid generating numerous GUIDs for each of the file.
Also is there any way I can change the name of the root directory I want the files to be installed. Currently, in our build system the files I want to install end up in a directory name "install". In the wxs file generated by heat it comes up as install. I was wondering if I could change it to the actual product name instead of "install".
Use one file per component - this avoids all sorts of problems (except .NET assemblies spanning multiple files). See the following thread: One file per component or several files per component?
Wix is a great framework for creating installers, but it has a steep learning curve. I strongly recommend you read a few sections of this great, online tutorial: https://www.firegiant.com/wix/tutorial/
If you are a "sample based tinkerer", you can find an even quicker, sample based tour in this article: http://www.codeproject.com/Tips/105638/A-quick-introduction-Create-an-MSI-installer-with
Wix is hands-on. Just focus on the samples, and focus on getting the components created and a major upgrade set up:
How to implement WiX installer upgrade? (modern, convenience way)
How to get WiX major upgrade working? (legacy way - more flexible, less convenient)
http://wixtoolset.org/documentation/manual/v3/howtos/updates/major_upgrade.html
Once you got that running the rest of the details fall into place by reading the documentation for whatever feature you need. Using Visual Studio / Votive with intellisense ensures that you can learn as you go with features such as shortcuts, ini files, xml files, dialogs, etc...
Another top tip is to use dark.exe (part of the Wix toolkit) to decompile existing MSI files. This yields Wix XML with code you can copy and paste into your own Wix files. I use other MSI tools to compile such MSI files, and then copy the sections I need into my Wix file - just to speed up the process of creating the Wix XML. Studying the decompiled XML is very educational - a real time saver.
UPDATE, May 2021: Some more links:
WiX Quick Start - Very long version
WiX Quick Start - Short version
If all the files are going to the same destination folder, then you can create one single COMPONENT with all the FILE within it. There is nothing stopping you to do that. You can then just create one GUID for that component. Also read these answers which talks about the advantages vs disadvantages of one component vs multiple components before you implement it: Answer1 Answer2. To Summarize:
You will have trouble with minor upgrades/repairs. If a component is
being updated, only the file designated as the KEYPATH is checked to see if
it is out of date: if it is up to date, all the others are ignored.
You'll also have difficulty if you want to add or remove files from each
component. Once released, a component is immutable (in terms of what files
are in it). The only way to update it without breaking component rules would
be to effectively remove and install the a new version of the MSI.
Understanding the component rules is key in Windows Installer and one file
per component makes the component rules easier to work with, which is why it
is the recommendation of many people here.
LINK
The root directory name can be changed by modifying the "Name" property for the DIRECTORY element.
I am in the process of creating an MSI for our product. I would like the product to be able to install side-by-side. So that I can install 1.0.0 first and later can add 1.0.1 so that the two versions are both installed.
I am using WiX to create the msi and would like to know how this can and should be done in Wix? For example
Do I need to create new Guids for all components?
How would i add the version info to wix or should i rename my product completely?
How can I create the projects so that releasing a new version requires minimal changes in the wix project?
Greetings,
Martijn
You should be able to get away with just changing the top-level productcode and UpgradeCode GUIDs to make your two products completely unrelated, and use the Productversion to identify the version. You can share component guids between products (that's how merge modules work) so that the guts of your installer (component definitions) needn't be tweaked and can still be shared.
You major challenge will be ensuring that the two decoupled products don't interfere with one another, for example by having the same default installation folder, start menu entries and the same Add/Remove programs entry. You might achieve this by including the product version number in the ProductName Property, which can look a bit techy in your install UI, but it isn't unheard of.
Regarding your first question: No, you don't need to.
But why?
I had difficulties to understand the windows installer rules in my side-by-side scenario.
You really need to understand the concepts of component rules (including when you need to brake them) and key paths. WiX doesn't abstract these aspects away.
This answer does already highlight possible interferences.
Let's consider a few examples.
The GUID of the component with the application executable does not need to be changed. This breaks the component rules, but it works, as both versions of the product define the same component in a non-interfering way.
A resource shared by both versions is not directly supported. A prominent example is the use of file extensions using ProgIDs, as shown here.
If you change the GUID (also happening when using the "*" GUID), the extension will be removed when uninstalling either version.
If you don't change the GUID, the extension will be retained, but point to the version which was installed most recently. You may go with this option as the lesser of two devils, supporting at least a scenario where users uninstall the versions in the same order in which they installed them.
There is a pitfall here: The extension needs to be the key path of the component. This makes the usage of the ProgID element problematic in a side-by-side scenario as you'll get the ICE69 warning in case you don't put the ProgID element in the same component as the referenced file. Further more, it's an implementation detail of WiX which registry entry it generates will be the key path.