Wix Formatted File Identifier

Posted on
Wix Formatted File Identifier 4,8/5 3092 reviews
Permalink
  1. Ctx Formatted File
  2. How Are Csv Files Formatted
  3. Python Formatted File Write

Join GitHub today

GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.

Sign up

Ctx Formatted File

Nov 30, 2004 - First, you can export your MSI file's tables to IDT file format, localize that text file then. In fact, the only documentation is WiX Localization file,.wxl files, schema. File Id='ExampleFile' Name='example.txt' src='example.txt'. This variable allows you to override the Id of the element in the WiX template. Patch files understood by the CPack WiX generator roughly follow this. You seem to have CSS turned off. Please don't fill out this field. You seem to have CSS turned off. Please don't fill out this field.

Branch:master
Find file Copy path
Windows file identifier
Cannot retrieve contributors at this time
<?xml version='1.0' encoding='utf-8'?>
<xs:schemaxmlns:html='http://www.w3.org/1999/xhtml'
xmlns:wix='http://schemas.microsoft.com/wix/2006/wi'
xmlns:xs='http://www.w3.org/2001/XMLSchema'
xmlns:xse='http://schemas.microsoft.com/wix/2005/XmlSchemaExtension'
targetNamespace='http://schemas.appsecinc.com/wix/SystemToolsExtension'
xmlns='http://schemas.appsecinc.com/wix/SystemToolsExtension'>
<xs:annotation>
<xs:documentation>
Windows Installer XML System Extension
This extension significantly simplifies various system tasks that aren't natively supported by Windows installer.
</xs:documentation>
</xs:annotation>
<xs:importnamespace='http://schemas.microsoft.com/wix/2006/wi' />
<xs:elementname='CopyFile'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Copies a file outside of component rules.
par Example:
code
<Wix .. xmlns:AppSecIncSystemTools='http://schemas.appsecinc.com/wix/SystemToolsExtension'>
<Product ..>
..
<Component .. >
<File Name='test1.txt' src='test1.txt' />
<File Name='test2.txt' src='test2.txt' />
</Component>
..
<AppSecIncSystemTools:CopyFile Source='[#test1]' Target='[#test1] (Copy)' CopyOnInstall='yes' />
<AppSecIncSystemTools:CopyFile Source='[#test2]' Target='[#test2] (Copy)' CopyOnInstall='yes'>
COPY_CONDITIONAL_FILES = 1
</AppSecIncSystemTools:CopyFile>
</Product>
</Wix>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the file should be copied. Must be blank or evaluate to true
for the file to be copied.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the file copy operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Source'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the source file to be copied.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Target'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the output target.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Overwrite'use='optional'>
<xs:annotation>
<xs:documentation>Specifies the overwrite behavior when the target file exists.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='yes' />
<xs:enumerationvalue='no' />
<xs:enumerationvalue='error' />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='MoveFile'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Moves a file outside of component rules.
par Example:
code
<Wix .. xmlns:AppSecIncSystemTools='http://schemas.appsecinc.com/wix/SystemToolsExtension'>
<Product ..>
..
<Component .. >
<File Name='test1.txt' src='test1.txt' />
<File Name='test2.txt' src='test2.txt' />
</Component>
..
<AppSecIncSystemTools:MoveFile Source='[#test1]' Target='[#test1] (Moved)' MoveOnInstall='yes' />
<AppSecIncSystemTools:MoveFile Source='[#test2]' Target='[#test2] (Moved)' MoveOnInstall='yes'>
MOVE_CONDITIONAL_FILES = 1
</AppSecIncSystemTools:MoveFile>
</Product>
</Wix>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the file should be moved. Must be blank or evaluate to true
for the file to be moved.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the file move operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Source'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the source file to be moved.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Target'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the output target.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MoveOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Move file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MoveOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Move file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Overwrite'use='optional'>
<xs:annotation>
<xs:documentation>Specifies the overwrite behavior when the target file exists.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='yes' />
<xs:enumerationvalue='no' />
<xs:enumerationvalue='error' />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='DeleteFile'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Deletes a file outside of component rules.
par Example:
code
<Wix .. xmlns:AppSecIncSystemTools='http://schemas.appsecinc.com/wix/SystemToolsExtension'>
<Product ..>
..
<AppSecIncSystemTools:DeleteFile File='[INSTALLLOCATION]OldFile.txt' DeleteOnInstall='yes' CheckIfExists='yes' />
</Product>
</Wix>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the file should be deleted. Must be blank or evaluate to true
for the file to be deleted.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the file deleted operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='File'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the file to be deleted.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete a file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete a file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CheckIfExists'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>
Check whether a file exists before deleting it.
If CheckIfExists is 'no' and the file doesn't exist, the custom action will fail.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='CompareVersion'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
The extension provides a simple method of correctly comparing two versions in dotted form.
It sets a property if the version is between the minimum and maximum versions.
par Example:
The following example uses a registry search to get the version of an installed
program, then uses SystemTools::CompareVersion to check that a suitable version is installed.
code
<Wix .. xmlns:AppSecIncSystemTools='http://schemas.appsecinc.com/wix/SystemToolsExtension'>
<Product ..>
..
<Property>
<RegistrySearch Type='raw'
Root='HKLM'
Key='SOFTWAREMicrosoftWindowsCurrentVersionUninstall{FFFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}'
Name='DisplayVersion' />
</Property>
<AppSecIncSystemTools:CompareVersion InstalledVersion='[PROGRAM_VERSION]' MinimumVersion='3.9' Property='ProgramVersionCorrect' />
<Condition Message='Incorrect version!'>
ProgramVersionCorrect OR Installed
</Condition>
..
</Product>
</Wix>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the version compare (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='InstalledVersion'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>The version to be checked</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MinimumVersion'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>The minimum version.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MaximumVersion'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>The maximum version.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Property'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>The property to be set if the installed version lies between the minimum and maximum versions.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='Execute'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Component' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
The extension simplifies authoring MSI packages that need semi-silent command-line execute behavior.
Execute will run any number of commands after InstallFiles, while ref ScheduleExecute lets you specify the runtime
behavior and additional runtime conditions just like for any regular custom action.
An optional condition that combines with options may be specified.
par Example:
code
<Component Guid='ca70ba08-0c57-4fa2-b6c1-57a00123e391'>
<File Name='SystemToolsMsi.wxs' Source='SystemToolsMsi.wxs' />
<AppSecInc:Execute CommandLine='cmd.exe /C copy SystemToolsMsi.wxs SystemToolsMsi_Copy.wxs /y' ErrorMessage='Failed to copy file.' ExecuteOnInstall='yes' ContinueOnError='yes' />
<AppSecInc:Execute CommandLine='cmd.exe /C del SystemToolsMsi_Copy.wxs' ErrorMessage='Failed to delete file.' ExecuteOnUnInstall='yes' ContinueOnError='yes' />
</Component>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the command is executed. If nested under a component, the condition is
combined with the parent's conditions.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the execute statement (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Directory'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Optional directory in which to execute the command.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CommandLine'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Command-line to execute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ErrorMessage'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Optional error message to display instead of a raw error.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ReturnCode'type='xs:integer'use='optional'>
<xs:annotation>
<xs:documentation>Optional return code that indicates success of the process, defaults to zero.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ContinueOnError'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Continue on error.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnRollback'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at rollback time.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='ScheduleExecute'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Component' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
To manually schedule an ref Execute action, use ScheduleExecute. This creates a custom action invoking Win32_Execute_Deferred with
the ID of the ScheduleExecute declaration. Explicit options, including ExecuteOnInstall and ExecuteOnUnInstall still apply and
ScheduleExecute may also be nested under a component to inherit the component's condition.
par Example:
code
<AppSecInc:ScheduleExecute CommandLine='cmd.exe /C copy Source.txt Target.txt' ExecuteOnInstall='yes' />
<AppSecInc:ScheduleExecute CommandLine='cmd.exe /C del Target.txt' ExecuteOnUnInstall='yes' />
<AppSecInc:ScheduleExecute CommandLine='cmd.exe /C del Target.txt' ExecuteOnRollback='yes' />
..
<InstallExecuteSequence>
<Custom Action='Scheduled_copy' After='InstallFiles'>NOT Installed</Custom>
<Custom Action='Scheduled_delete' After='InstallFiles'>Installed</Custom>
<Custom Action='Scheduled_rollback' After='InstallFiles'>NOT Installed</Custom>
</InstallExecuteSequence>
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the command is executed. If nested under a component, the condition is
combined with the parent's conditions.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the execute statement (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Directory'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Optional directory in which to execute the command.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CommandLine'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Command-line to execute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ErrorMessage'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Optional error message to display instead of a raw error.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ReturnCode'type='xs:integer'use='optional'>
<xs:annotation>
<xs:documentation>Optional return code that indicates success of the process, defaults to zero.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ContinueOnError'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Continue on error.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnRollback'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Execute command at rollback time.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='TemplateFile'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Component' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Implements formatting of a template file.
The extension allows processing of template files in-place or into a new file.
To evaluate a property called PROPERTYNAME in a template file, write [PROPERTYNAME].
Non-declared properties are not evaluated. Declared properties with empty values are evaluated to their empty value.
An optional condition that combines with options may be specified as a Condition node under TemplateFile.
par Example:
code
<SystemTools:TemplateFile Source='[#File_template]' Target='[INSTALLLOCATION]File.txt' ExecuteOnInstall='yes'>
<SystemTools:TemplateFileProperty Name='INSTALLLOCATION' Value='[INSTALLLOCATION]' />
<SystemTools:TemplateFileProperty Name='TEST' Value='test' />
<SystemTools:TemplateFileProperty Name='Filename' Value='File.txt' />
</SystemTools:TemplateFile>
endcode
In addition to properties specified by TemplateFileProperty, built-in properties are available. Those are not all
MSI properties, only those that were declared at build time. If the property has changed during installation, its old
value is provided by default: overwrite the property value with the current one by explicitly declaring
TemplateFileProperty with a value.
code
<SystemTools:TemplateFileProperty Name='PROPERTY1' Value='[PROPERTY1]' />
endcode
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choiceminOccurs='0'maxOccurs='unbounded'>
<xs:elementref='TemplateFileProperty'/>
<xs:elementref='wix:Condition' />
</xs:choice>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the template file (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Source'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the template file to be processed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Target'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Target file to be written. When omitted, the source file is processed in-place and overwritten.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Process the template file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Process the template file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='ExecuteOnReInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Process the template file at reinstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<!--
<xs:attribute name='ExecuteOnRollback' use='optional' type='YesNoType'>
<xs:annotation>
<xs:documentation>Process the template file at rollback time.</xs:documentation>
</xs:annotation>
</xs:attribute>
-->
</xs:complexType>
</xs:element>
<xs:elementname='TemplateFileProperty'>
<xs:annotation>
<xs:appinfo>
<xse:parentref='TemplateFile' />
</xs:appinfo>
<xs:documentation>
Publishes a single property for a template file.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the property (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Name'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the property to be processed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Value'type='xs:string'use='optional'>
<xs:annotation>
<xs:documentation>Value of the property.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='CopyFiles'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Copies a set of files outside of component rules, with subdirectories.
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the files should be copied. Must be blank or evaluate to true
for the files to be copied.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the files copy operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Source'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Directory containing files to be copied.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Wildcard'type='xs:string'use='optional'default='*.*'>
<xs:annotation>
<xs:documentation>Wildcard of files to be copied.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Target'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the target directory.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Recurse'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>
Recurse into subdirectories. Behaves like xcopy, copying files that match Wildcard from
subdirectories.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<!--
<xs:attribute name='CreateEmptyDirectories' use='optional' type='YesNoType'>
<xs:annotation>
<xs:documentation>Create empty subdirectories.</xs:documentation>
</xs:annotation>
</xs:attribute>
-->
<xs:attributename='Overwrite'use='optional'>
<xs:annotation>
<xs:documentation>Specifies the overwrite behavior when the target file exists.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='yes' />
<xs:enumerationvalue='no' />
<xs:enumerationvalue='error' />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='MoveFiles'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Moves a set of files outside of component rules, with subdirectories.
Operates on a best-effort basis, ie. neither source nor target directories need to exist for the operation
to succeed. Does not move empty directories, only creates target directories that have files.
The move file operation will fail and the installation will rollback on first error.
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the files should be moved. Must be blank or evaluate to true
for the files to be moved.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the files move operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Source'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Directory containing files to be moved.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Wildcard'type='xs:string'use='optional'default='*.*'>
<xs:annotation>
<xs:documentation>Wildcard of files to be moved.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Target'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Name of the target directory.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MoveOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Move file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='MoveOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Move file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Recurse'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>
Recurse into subdirectories. Behaves like xcopy, moving files that match Wildcard from
subdirectories, then deletes the individual files that have been moved.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteEmptyDirectories'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete leftover empty subdirectories.</xs:documentation>
</xs:annotation>
</xs:attribute>
<!--
<xs:attribute name='CreateEmptyDirectories' use='optional' type='YesNoType'>
<xs:annotation>
<xs:documentation>Create empty subdirectories.</xs:documentation>
</xs:annotation>
</xs:attribute>
-->
<xs:attributename='Overwrite'use='optional'>
<xs:annotation>
<xs:documentation>Specifies the overwrite behavior when the target file exists.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='yes' />
<xs:enumerationvalue='no' />
<xs:enumerationvalue='error' />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='DeleteFiles'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Product' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Module' />
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='Fragment' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Deletes a set of files outside of component rules, with subdirectories.
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase='xs:string'>
<xs:annotation>
<xs:documentation>
Condition that determines if the files should be deleted. Must be blank or evaluate to true
for the files to be deleted.
</xs:documentation>
</xs:annotation>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the files delete operation (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Path'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Path containing files to be deleted.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Wildcard'type='xs:string'use='optional'default='*.*'>
<xs:annotation>
<xs:documentation>Wildcard of files to be deleted.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete file at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete file at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Recurse'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>
Recurse into subdirectories. Deletes files, directories and subdirectories.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='DeleteEmptyDirectories'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Delete leftover empty subdirectories.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:elementname='RegistryKeyCopy'>
<xs:annotation>
<xs:appinfo>
<xse:parentnamespace='http://schemas.microsoft.com/wix/2006/wi'ref='RegistryKey' />
</xs:appinfo>
<xs:documentation>
<![CDATA[
Defines a registry key copy and restore operation that can be scheduled across a major upgrade.
par Example:
The following example will backup the HKEY_LOCAL_MACHINESoftwareAppSecIncSystemToolsMsi key before it's written by
the installer and roll back the change if installation fails.
code
<Component Guid='A9A913DB-CDA9-486c-B4C6-2A109661AEBD'>
<RegistryKey Action='create' Root='HKLM' Key='SOFTWAREAppSecIncSystemToolsMsi'>
<RegistryValue Name='ProductCode' Value='[ProductCode]' Action='write' Type='string' />
<AppSecInc:RegistryKeyCopy TargetRoot='HKEY_LOCAL_MACHINE' TargetPath='SOFTWAREAppSecIncSystemToolsMsiBackup'
CopyOnInstall='yes' RestoreOnRollback='yes' Overwrite='yes' CheckIfExists='yes' />
</RegistryKey>
</Component>
endcode
Note that Windows Installer already performs the restore operation, but it is not designed to work across a major
upgrade. The default scheduling of this extension simply enables registry key backup. In order to perform a
backup and rollback in a major upgrade scneario you must schedule the backup custom action before a previous
version of the product is uninstalled.
code
<Custom Action='Win32_RegistryCopy_Deferred_Install' Before='RemoveExistingProducts'>UpgradingCondition</Custom>
endcode
The extension will now backup the registry key before uninstall happens, then restore it on rollback of the major
upgrade in an event of failure.
]]>
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choiceminOccurs='0'maxOccurs='unbounded'>
<xs:elementref='wix:Condition' />
</xs:choice>
<xs:attributename='Id'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Identifier for the registry key copy (primary key).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='TargetRoot'default='HKEY_LOCAL_MACHINE'type='RegistryKeyType'>
<xs:annotation>
<xs:documentation>Target registry root.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='TargetPath'type='xs:string'use='required'>
<xs:annotation>
<xs:documentation>Target registry key path.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CheckIfExists'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Check whether the source registry key exists before performing a copy operation.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='Overwrite'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Overwrite target key if it exists.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy registry key at install time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='CopyOnUnInstall'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Copy registry key at uninstall time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='RemoveSource'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Remove the source registry key after copy (ie. move).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributename='RestoreOnRollback'use='optional'type='YesNoType'>
<xs:annotation>
<xs:documentation>Restore registry key contents on rollback.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:simpleTypename='YesNoType'>
<xs:annotation>
<xs:documentation>Values of this type will either be 'yes' or 'no'.</xs:documentation>
</xs:annotation>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='no' />
<xs:enumerationvalue='yes' />
</xs:restriction>
</xs:simpleType>
<xs:simpleTypename='RegistryKeyType'>
<xs:annotation>
<xs:documentation>Windows registry key types.</xs:documentation>
</xs:annotation>
<xs:restrictionbase='xs:NMTOKEN'>
<xs:enumerationvalue='HKEY_LOCAL_MACHINE' />
<xs:enumerationvalue='HKEY_CURRENT_USER' />
<xs:enumerationvalue='HKEY_CURRENT_CONFIG' />
<xs:enumerationvalue='HKEY_CLASSES_ROOT' />
<xs:enumerationvalue='HKEY_USERS' />
</xs:restriction>
</xs:simpleType>
</xs:schema>
  • Copy lines
  • Copy permalink

Tonight we pick up where I left off last week and continue with the topic of localizing your MSI file. If you haven't read last week's blog entry, you should do that now. Harvest moon back to nature. Yes, it's pretty long. Don't worry I'll wait. There's lots of good background information in there.


Great, I want to cover a couple more things before we really get started. First, just like in my previous blog entry all of the information presented here works equally well for Merge Modules (MSM files) as it does for MSI files. I'll be using an MSI file in my example and I'll use the words 'MSI file' a lot (that's how I get such a high page rank for Windows Installer stuff.. just kidding) because I'm lazy and get tired of writing MSI/MSM file. Second, I am using the latest build of the WiX toolsetv2.0.2328.0 in my examples. This is important because, as you'll note in the release notes, I fixed many localization issues with this release of the toolset. If you want to follow along, be sure you have a recent version of the WiX toolset.


Today there are really two ways to localize your MSI file. Step 3 and step 4 of the Localization Example in the Windows Installer SDK that I pointed at last week demonstrate those two methods. First, you can export your MSI file's tables to IDT file format, localize that text file then import the IDT file back into your MSI. This method is the fastest way to update information in your MSI file. However, it also requires the most care because you must ensure the codepage of the IDT file matches the codepage of the MSI file or the import will fail with terribly helpful error messages like, 'Failed to import your IDT file for some reason. Have a nice day' (note: ::MsiGetLastErrorRecord() will give you more information about the error but it rarely gives you the exact answer to the issue). It is interesting to note that the remarks in ::MsiDatabaseImport() function discourage using this method for updating your MSI file because of the codepage and other IDT encoding issues (like tabs and carriage returns).


The second way to localize data in your MSI file is to use the Windows Installer SQL Syntax to update the appropriate columns. This method is arguably easier than the previous method because you don't have to worry about encoding tabs or carriage returns and the APIs will attempt to encode your text the best it can to match the MSI file's current codepage. Unfortunately, this method is also slower than the previous method because the Windows Installer SQL processor is not particularly speedy.


So how about a solution that provides you, the setup developer, with the fastest method to create localized MSI files without needing to worry too much about encoding all of your data in IDT files correctly? What if all you needed to do was to provide the localized data and the codepage for that data (codepage is still necessary because I don't know how to look at several random strings of text and accurately reverse engineer the codepage from them)? What if you could actually compile all of your source code files once then only link the object files together once for each language? How? Well with the WiX toolset, of course.


Admittedly, the WiX toolset's localization features are some of the least documented features in the WiX toolset. In fact, the only documentation is WiX Localization file, .wxl files, schema (wixloc.xsd) and the code in light.cs that processes the .wxl files. So I'm here now to turn that all around with a step-by-step example.


Let's look at a small example source file that installs a simple file with a shortcut. Let's call this source file 'example.wxs':


Note, to compile the code above with candle.exe, you'll need to replace 'PUT-GUID-HERE' with your own GUID. I don't provide GUIDs in my examples because people like to copy the examples then forget to change the GUID before shipping. Of course, that would be an immediate Component Rule violation and I don't want to be responsible for that. Also, before we can link that code with light.exe, we'll need to create a text file called, 'example.txt'. Here's what my example.txt file looks like:


Okay, after creating example.wxs (and adding your own GUID) and creating example.txt, you should be able to create an 'example.msi' file by compiling and linking the files like so:


As always, no news from light.exe is good news. You can install the newly created MSI file using 'msiexec /i example.msi' and should notice a new shortcut in your ProgramMenuFolder ('Start' -> 'All Programs' on Windows XP). But I'm sure for you old WiX toolset hacks out there this example is boring. So, let's get to localizing.


If you used the preprocessor, you are already familiar with $(var.VAR) for defined variables and $(env.VAR) for environment variables. Localization in the WiX toolset is done by inserting 'localization variables'. Localization variables look like $(loc.VAR). Let's look at our modified source file:


You should again be able to compile that file but if you try to link you should see error messages such as, 'light.exe : fatal error LGHT0023: Localization string 'FeatureTitle' unknown. Ensure that the $(loc.FeatureTitle) is defined.' That error message basically means we did not provide a Localization file with all of the localizable identifiers and text. So, now we need to create our first .wxl file. I've called mine example1033.wxl and it goes a little like this:


How Are Csv Files Formatted

Now, to get our MSI file back.


I want to note that (barring any typos) this MSI file should be identical to the first MSI file we created. I also want to note that this will be the last time we compile the example.wxs. Since we have specified all of our localization variables we no longer need to compile to get changes in our MSI file. All we need to do localize our example1033.wxl file into other languages. Since, I don't know any other languages, I'm going to localize our example1033.wxl file into the 'Foo language' and use the Japanese LCID, 1041, since I happen to remember that one. Here's the example1041.wxl file localized into the 'Foo language':


Notice how elegant the 'Foo language' is. The elegance really is lost in text format. So much of the 'Foo language' is transmitted via the pitch and duration of each word. But I digress. Let's build our 'Foo language' example.msi file. This will just stomp over our previous example.msi so make sure you uninstall the previous example.msi file using 'msiexec /x example.msi' (or you'll have to go to Control Panel -> Add/Remove Programs). Let's link (and only link) our MSI file:


Now if you install the MSI file you are likely to see square boxes for the ActionText during the progress dialog box. I believe this occurs when you don't have the Japanese fonts necessary to display the Windows Installer's default text messages. In any case, I don't have Japanese fonts installed on my machine so I see square boxes. However, square boxes or no square boxes everything should install just fine. After installing, you too should see a 'Foo' shortcut in your ProgramMenuFolder.


That's all there is to .wxl files. Hopefully, you can see how the Localization files can greatly simplify the relationship between you, your localizers, and your setup. I would also like to note that .wxl files are relatively new constructs in the WiX toolset so if you have suggestions how to improve them please feel free to send your feedback to the 'wix-devs at sourceforge.net' mailing list.


And that brings me to my final point. There is one very fatal flaw in the code above. I debated delaying this blog entry to fix the issue but decided the content here was valuable even with the mistake. Have you found it yet? Look closely at the Component/@Guid attribute. Did that value change each time you created a completely different Component like the step 9 in the Localization Overview suggests? Probably not because you can't currently localize GUID values as described by this bug on SourceForge. However, the value should change because you have very different Shortcuts in the two Components (and the example.txt file is installed to different locations so there is no overlap). So, I apologize profusely for creating an example that violates the Component Rules and I will fix the bug ASAP.


Python Formatted File Write

In the meantime, have fun playing with your .wxl files and keep coding.


Update: I fixed the typo that Peter mentions in his comment below.Grant taylor obituary.