WiX Installer: using xslt with heat.exe to update attributes
You have two different defined namespaces:
- In XML:
http://schemas.microsoft.com/wix/2006/wi
- In XSLT:
http://schemas.microsoft.com/wix/2006/wix
As far as I know, correct namespace for WiX is http://schemas.microsoft.com/wix/2006/wi
. So you should change your XSLT.
XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:my="my:my"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match='wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Component/wix:File[@Id and not (@Id = "EmailGenerationService.exe")]'> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:attribute name="KeyPath"> <xsl:text>no</xsl:text> </xsl:attribute> </xsl:copy> </xsl:template></xsl:stylesheet>
Input XML:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Fragment> <DirectoryRef Id="INSTALLLOCATION"> <Component Id="Dollar.Common.dll" Guid="{2BCD0767-2383-47CF-B1BF-325FA4A3264F}"> <File Id="Dollar.Common.dll" KeyPath="yes" Source="$(var.FileSource)\Dollar.Common.dll" /> </Component> <Component Id="Dollar.Common.Exceptions.dll" Guid="{B7238091-76D1-42F5-A3B4-A539DFF3BD92}"> <File Id="Dollar.Common.Exceptions.dll" KeyPath="yes" Source="$(var.FileSource)\Dollar.Common.Exceptions.dll" /> </Component> <Component Id="Dollar.Common.Exceptions.pdb" Guid="{43711979-747D-49C9-BAE4-ECD44FAF5E67}"> <File Id="Dollar.Common.Exceptions.pdb" KeyPath="yes" Source="$(var.FileSource)\Dollar.Common.Exceptions.pdb" /> </Component> <Component Id="Dollar.Common.Logging.dll" Guid="{59F9ABF3-5F68-410C-BC96-0556282F1E04}"> <File Id="Dollar.Common.Logging.dll" KeyPath="yes" Source="$(var.FileSource)\Dollar.Common.Logging.dll" /> </Component> </DirectoryRef> </Fragment></Wix>
Output XML:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Fragment> <DirectoryRef Id="INSTALLLOCATION"> <Component Id="Dollar.Common.dll" Guid="{2BCD0767-2383-47CF-B1BF-325FA4A3264F}"> <File Id="Dollar.Common.dll" Source="$(var.FileSource)\Dollar.Common.dll" KeyPath="no" /> </Component> <Component Id="Dollar.Common.Exceptions.dll" Guid="{B7238091-76D1-42F5-A3B4-A539DFF3BD92}"> <File Id="Dollar.Common.Exceptions.dll" Source="$(var.FileSource)\Dollar.Common.Exceptions.dll" KeyPath="no" /> </Component> <Component Id="Dollar.Common.Exceptions.pdb" Guid="{43711979-747D-49C9-BAE4-ECD44FAF5E67}"> <File Id="Dollar.Common.Exceptions.pdb" Source="$(var.FileSource)\Dollar.Common.Exceptions.pdb" KeyPath="no" /> </Component> <Component Id="Dollar.Common.Logging.dll" Guid="{59F9ABF3-5F68-410C-BC96-0556282F1E04}"> <File Id="Dollar.Common.Logging.dll" Source="$(var.FileSource)\Dollar.Common.Logging.dll" KeyPath="no" /> </Component> </DirectoryRef> </Fragment></Wix>
I won't answer your original question. :)
I have read that I nned to set the keyPath to “no” for all my files, with the exception of the .exe
I think you were mislead. In reality the ServiceInstall table has a column Component_
, and according to MSDN:
to install this service using the InstallService table, the KeyPath for this component must be the executable file for the service.
It doesn't mean the non-exe files in other components should have @KeyPath='no'
. It just says that the EXE file of the service should reside in a separate component and must be the key path of it.
The key path is a very important concept of the MSI technology. You can read more about it here, see the description of the KeyPath column.
Now, if we get back to your original question - no, you don't have to tweak the heat output the way you mentioned. It will generate the WiX authoring you need by default.
May I suggest a different approach?
<xsl:template match="@KeyPath[parent::wix:File[parent::wix:Component[parent::wix:DirectoryRef[parent::wix:Fragment[parent::wix:Wix]]]] and . != 'EmailGenerationService.exe']"> <xsl:attribute name="KeyPath"> <xsl:value-of select="'no'"/> </xsl:attribute></xsl:template>
Just change your template matching to the above and you should have the correct result.