Professional Documents
Culture Documents
Rainer Stropek
software architects gmbh
WiX
Web http://www.timecockpit.com
Mail rainer@timecockpit.com
Twitter @rstropek
Der WiX-Buildprozess
Conditions
Launch Conditions
Feature Conditions
Action/Installed States
Erklärung anhand von live gezeigten Beispielen, bei denen die Teilnehmer mitmachen können
ClickOnce deployment
Self-updating applications
No shared components (best practice for MSI, too), non-administrative install (possible with MSI, too)
Need a demo?
For details see MSDN
Process
Identify features for end users
Organize application into components
Create installation database (WiX)
Validate installation package
Important Concepts
Installation process
Acquisition: Interactive part, generate installation script
Execution: Run installation script
Rollback: Undo system changes in case of an error
Installation types
Install, Maintain, Repair, and Uninstall
Installation On-Demand and Advertisement (JIT installation)
Patches and Upgrades
Administrative installation
Important Concepts
Features
Part of the application’s functionality
Can be installed independently
Visible to end users
Components
Features consist of components
Unit of installation
Hidden from the user
Installation sources
Local MSI file
Install from server
Download from Internet
Rather old Concepts (not covered here)
Concurrent installations
Deprecated
Demo
Tools
Important tools for working with WiX
Visual Studio
Project templates
Build tasks
WiX Tools
Command Line
candle.exe
WiX Compiler (.wxs .wixobj)
light.exe
WiX Linker (.wixobj/lib .msi)
lit.exe
WiX Libraries (.wxs .wixlib)
torch.exe, pyro.exe
Patches (.msp)
WiX Tools
Compile Process
*.wixlib
lit.exe
*.wxs *.wixobj
*.msi/msm
candle.exe
light.exe
The following statement generates Product.wixobj
candle Product.wxs
Command Line
Now we can generate the MSI from the .wixobj file Building MSI on command line
Note that this examples uses an installer UI (details later)
light Product.wixobj -ext WixUIExtension
WiXEdit
http://wixedit.sourceforge.net/
Install Options
msiexec
</package | /i> <Product.msi> Windows Installer
Installs or configures a product
</uninstall | /x> <Product.msi | ProductCode>
Uninstalls the product
Important command line
Logging Options arguments
/l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile> Get full list of arguments with
* - Log all information, except for v and x options msiexec /?
/log <LogFile>
Equivalent of /l* <LogFile>
Well-formed XML
“Toolable”
Can be version controlled,
merged, diff‘ed, etc.
RequiredVersion
Minimum WiX toolset version
Important in the team
Can be found in Codeplex
Product Element (doc)
Similar to main method in C#
Describes the product that is inside the installer package
Only one Product element is allowed
</Product>
</Wix>
Package Element (doc)
Describes the installer package
Id: Can be omitted
WiX will pick one for you
Descriptions
Manufacturer, Description, Keywords, etc.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product …>
Package
Example
<Package InstallerVersion="301"
Compressed="yes"
InstallScope="perMachine"
Manufacturer="software architects"
Use MediaTemplate (doc)
Description="time cockpit Installer" to embed CAB files into
Keywords="time,cockpit,Installer,MSI"
Comments="(c) software architects" />
MSI
Use Media (doc) element if you
<MediaTemplate EmbedCab="yes" /> want to separate CAB files from
MSI (not covered here)
…
</Product>
</Wix>
Directory Element (doc)
Defines the directory layout used to install the product
Id: Key used to identify the directory
Root Directory element must have ID=„TARGETDIR“ and Name=„SourceDir“
Predefined folder IDs see MSDN
<!--Directory structure-->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyProgramDir" Name="timecockpit" />
<Directory Id="ProgramMenuFolder">
<Directory Id="MyShortcutsDir“
Name="software architects" />
</Directory>
</Directory>
</Directory>
…
</Product>
</Wix>
Handling Files
Recommendation: Wrap each File (doc) into its own Component (doc) element
Components, Files
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product …>
…
<Directory Id="TARGETDIR" Name="SourceDir">
Example
<Directory Id="ProgramFilesFolder">
<Directory Id="MyProgramDir" Name="timecockpit" />
<File
Guid="4A626372-1FA8-4F37-B6AA-13FC7A7C6228">
Handling Files
Id="FILE_MyProgramEXE„
Source="$(var.FilesPath)MyProgram.exe"
KeyPath="yes" />
</Component>
Use $(var.VarName) to
access preprocessor
variables
Use $(var.ProjectName.
TargetDir) to reference
other projects in your
solution (doc)
Feature (doc) Element
Features are groups of components that can be installed together
Drives the content of the feature tree in the installation wizard
Features can be nested if necessary
<!--Features-->
<Feature Id="InstallMeFeature" Title="Main Product"
Level="1">
<ComponentRef Id="CMP_InstallMeTXT" />
</Feature>
<UIRef Id="WixUI_FeatureTree"/>
</Product>
</Wix>
Additional File Handling Tips
CopyFile (doc) element
Copy (=duplicate) files using CopyFile as child of File
Use DestinationDirectory attribute to reference the ID of a Directory element
Use DestinationProperty attribute to reference directory name in a property
Shortcuts
<Directory Id="ProgramFilesFolder">
<Directory Id="MyProgramDir" Name="Awesome Software" />
<Directory Id="ProgramMenuFolder">
<Directory Id="MyShortcutsDir" Name="Awesome Software" />
Example
</Directory>
</Directory>
</Directory>
…
<Icon Id="icon.ico" SourceFile="myIcon.ico"/>
<DirectoryRef Id="MyShortcutsDir">
<Component Id="CMP_DocumentationShortcut"
Guid="33741C82-30BF-41AF-8246-44A5DCFCF953">
<Shortcut Id="DocumentationStartMenuShortcut"
Name="Awesome Software Documentation"
Description="Read Awesome Software Documentation"
Target="[MyProgramDir]InstallMe.txt“
Icon="icon.ico" />
<Shortcut Id="UninstallShortcut"
Name="Uninstall InstallPractice"
Description="Uninstalls Awesome Software"
Target="[System64Folder]msiexec.exe"
Arguments="/x [ProductCode]" />
<RemoveFolder Id="RemoveMyShortcutsDir" On="uninstall" />
<RegistryValue Root="HKCU"
Key="Software\Microsoft\AwesomeSoftware"
Name="installed" Type="integer"
Value="1" KeyPath="yes" />
</Component>
</DirectoryRef>
WiX Basics
Example
Create shortcuts
Open installed file
Uninstall
See GitHub
Demo
Fragments
Used to structure large projects into multiple .wxs files
Main source file: Product element acts as the root
All other source files: Fragment (doc) element acts as the root
Shortcuts
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<ComponentGroup Id="ComponentGroup1"
Directory="INSTALLLOCATION">
Example
…
</ComponentGroup>
</Fragment>
</Wix>
<Feature Id="ProductFeature“
Title="My Product“
Level="1">
<ComponentGroupRef Id="ComponentGroup1" />
</Feature>
Harvesting
Auto-generates .wxs from various sources
Sources include directories, IIS websites, Visual Studio projects, etc.
heat.exe (doc)
Important switches
Guid generation (-ag for Guid=“*”, -gg for letting heat generate Guids)
-pog for selecting output groups of VS project (e.g. Binaries, Symbols, etc.)
No type system
Demo
<Component Id="CMP_Service" Directory="INSTALLFOLDER">
<!-- Install service executable -->
<File Id="FILE_EventLoggingService"
Installing a Service
Source="$(var.ServiceToInstall.TargetPath)"
KeyPath="yes" />
<InstallExecuteSequence>
<Custom Action="MyAction" After="InstallInitialize" />
</InstallExecuteSequence>
Running embedded VBScript or JScript code Script, script source as element‘s content
Return
asyncNoWait async, may continue after installer completes
asyncWait async but installer waits at the end
check synchronous, installer check return value
ignore synchronous, installer ignores return value
Custom (doc)
After/Before
Sequence after/before custom action should be scheduled
Content
Condition of the action
Custom Actions
First-time install dialog sequence: First-time install dialog sequence: First-time install dialog sequence: First-time install dialog sequence: WixUI_Advanced offers a two-click
- WixUI_WelcomeEulaDlg - WixUI_WelcomeDlg - WixUI_WelcomeDlg - WixUI_WelcomeDlg install (EULA checkbox and Install
- WixUI_LicenseAgreementDlg - WixUI_LicenseAgreementDlg - WixUI_LicenseAgreementDlg button) and offers an Advanced
Maintenance dialog sequence: - WixUI_CustomizeDlg - WixUI_InstallDirDlg - WixUI_SetupTypeDlg button that lets users choose per-
WixUI_MaintenanceWelcomeDlg - WixUI_VerifyReadyDlg - WixUI_VerifyReadyDlg - WixUI_VerifyReadyDlg machine or per-user installs, install
- WixUI_MaintenanceTypeDlg - WixUI_DiskCostDlg - WixUI_DiskCostDlg - WixUI_CustomizeDlg path, and features.
- WixUI_VerifyReadyDlg - WixUI_DiskCostDlg
Maintenance dialog sequence: Maintenance dialog sequence: - WixUI_BrowseDlg
Patch dialog sequence: - WixUI_MaintenanceWelcomeDlg - WixUI_MaintenanceWelcomeDlg
- WixUI_WelcomeDlg - WixUI_MaintenanceTypeDlg - WixUI_MaintenanceTypeDlg Maintenance dialog sequence:
- WixUI_VerifyReadyDlg - WixUI_CustomizeDlg - WixUI_InstallDirDlg - WixUI_MaintenanceWelcomeDlg
- WixUI_VerifyReadyDlg - WixUI_VerifyReadyDlg - WixUI_MaintenanceTypeDlg
- WixUI_CustomizeDlg
Patch dialog sequence: Patch dialog sequence: - WixUI_VerifyReadyDlg
- WixUI_WelcomeDlg - WixUI_WelcomeDlg
- WixUI_VerifyReadyDlg - WixUI_VerifyReadyDlg Patch dialog sequence:
- WixUI_WelcomeDlg
- WixUI_VerifyReadyDlg
Built-in UI Sequences
WiX Preprocessor
<?define UpgradeCode = "{89CC…}" ?>
Compiler Variables
<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define Config = "Debug" ?>
<?define ProductId =
"{89CC4C03-1059-4523-8670-50DEA04B9892}" ?>
Recommendation: Put
<?define UpgradeCode = variables into .wxi file
"{49D09A05-12D9-461E-8DEE-9DD5615AF9FE}" ?>
System variables
$(sys.CURRENTDIR)
$(sys.SOURCEFILEDIR)
$(sys.SOURCEFILEPATH)
$(sys.PLATFORM) (arch flag from candle.exe)
<?if $(var.ProcessorArchitecture)=x64 ?>
<Property Id="KB2160841INSTALLED">
<!-- security update for .net framework, CLR bug! -->
Preprocessor
<DirectorySearch Id="Windows" Path="[WindowsFolder]"> Doc
<DirectorySearch Id="MS.NET" Path="Microsoft.NET">
<DirectorySearch Id="clrjitDir" Depth="3"
AssignToProperty="yes">
<FileSearch Id="clrjit" Name="clrjit.dll"
Other preprocessor
MinVersion="4.0.30319.201" /> statements
</DirectorySearch> <?foreach …?>
</DirectorySearch> <?error …?>
</DirectorySearch>
</Property>
<Condition Message="!(loc.ErrorKB2160841NotInstalled)">
<![CDATA[Installed OR KB2160841INSTALLED]]>
</Condition>
<?endif?>
Localization Variables
xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="LANG" Overridable="yes">1031</String>
<String Id="LicenseRtf">\Lang\de-de\License_de-DE.rtf</String>
<String Id="Error32BitOn64BitMachine" Overridable="yes">…</String>
<String Id="ErrorKB2160841NotInstalled"
Overridable="yes">…</String>
</WixLocalization>
<CustomAction Id="CA_ErrorKB2160841NotInstalled"
Error="!(loc.ErrorKB2160841NotInstalled)" />
<Product Id="*"
Name="PracticeWix"
Language="1033"
Version="!(bind.fileVersion.MyApplicationEXE)"
Manufacturer="Awesome Company"
UpgradeCode="3c1789e3-5b3d-4cb5-9c73-a03f2cc09c26">
Upgrading and Patching
Upgrades
Upgrade types
Major upgrades
Minor upgrades
Small updates
For details see also MSDN
Increment Product.Version
Recommendation: Automate version numbering in build process
Small Upgrades
Like minor upgrades, smaller in scope
No changes in ProductCode and Version
For details see MSDN
Patch Creation
Old.msi/.wixpdb
Compare old/new .wixpdb
using torch
Result: .wixmst transform file
torch.exe Delta.wixmst pyro.exe Path.msp
Combine transform file
with .wixmsp patch file
New.msi/.wixpdb Patch.wixmsp using pyro
Result: .msp patch file
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
.wixmsp File
AllowRemoval="yes"
Manufacturer="software architects"
MoreInfoURL="http://www.timecockpit.com/"
DisplayName="Sample Patch"
Description="Small Update Patch"
Classifications
Classification="Update"> Critical Update, Hotfix, Security
Rollup, Security Update,
<Media Id="5000" Cabinet="RTM.cab"> Service Pack, Update, and
<PatchBaseline Id="RTM"/> Update Rollup
</Media>
Patch Slipstreaming
Fancy installer UI
Standard bootstrapper UI (doc) or
Custom UI based on Windows Presentation Foundation (XAML)
<?xml version="1.0" encoding="UTF-8"?>
Boostrapper
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Composite App (with Bootstrapper)"
Version="1.0.0.0"
Example
Manufacturer="software architects"
UpgradeCode="1df9e3b2-d6a5-4e06-b289-078c5a0720ac">
<!-- Bundle can only be installed on Windows >= 7 --> For details see WiX docs
<bal:Condition Message="Requires Windows >= 7">
<![CDATA[VersionNT >= v6.1]]>
</bal:Condition> VersionNT
<BootstrapperApplicationRef Burn built-in variables (doc)
Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication
LicenseFile="License.rtf"/>
</BootstrapperApplicationRef>
<Chain>
<MsiPackage Id="Shell" SourceFile="$(var.Shell.TargetDir)Shell.msi">
<!-- Pass a property to Shell installer to install SDK, too -->
<MsiProperty Name="INSTALLSDK" Value="1" />
</MsiPackage>
<RollbackBoundary />
<MsiPackage Id="Extension"
After="Shell"
SourceFile="$(var.Extension.TargetDir)Extension.msi" />
</Chain>
</Bundle>
</Wix>
Boostrapper Tips
Localizable just like MSIs (doc)
Upgrades
Higher version in the same UpgradeCode newer MSIs are upgraded
Rainer Stropek
software architects gmbh