不通过加热生成所需的wxs输出,而是为应用程序快捷方式生成xslt

时间:2015-08-21 07:01:02

标签: xslt wix

我是wix和xslt的新手。我可以使用wixedit GUI构建安装文件,但需要自动化该过程。我正在使用Windows构建机器。

我正在使用heat来收集所有文件并进行xsl转换以尝试获得类似于我通过wixedit创建安装包时得到的结果。

使用的命令是:

%WX_HOME%\heat.exe dir "%BUILD_DEST%" -ag -gg -nologo -projectname "%PROJ%" -template product -sfrag -v -platform x86 -var var.AppSource -t %TOOLS_SRC_DIR%\heat.xsl -out %WX_WXS_FILE%
%WX_HOME%\candle.exe -arch x86 -nologo -out %BUILD_DEST%\%PROJ%.wixobj -v %WX_WXS_FILE% -dAppSource=%BUILD_DEST% -ext WixUtilExtension
%WX_HOME%\light.exe -nologo -out "%INSTALL_FILE%" -v %BUILD_DEST%\%PROJ%.wixobj

通过xslt我正在添加一个"文件"属性到每个文件条目并在查询中使用它来查找给定的应用程序可执行文件以添加所需的快捷方式。

经过多次xsl试错和互联网搜索,我被困住了。在下面的xsl中,我用" FIXME"标记了2个注释掉的部分。以及该部分引起的问题描述。

基本上,我认为至少需要两个阶段的修正:修复EXE_FILE的错误。然后,可以添加桌面和程序菜单快捷方式,包括在product元素内生成图标元素。

使用下面显示的heat.xsl文件,灯会产生错误

LGHT0094: Unresolved reference to symbol 'Component:EXE_FILE' in section 'Product:{A0953F8D-5F10-47A4-BF70-A2B68B6399D8}'.

但是,EXE_FILE正确地是输出中可执行文件的id属性。 目录有类似的错误消息:DesktopFolder,目录:ProgramMenuDir,Icon:DesktopIcon.exe和Icon:StartMenuIcon.exe。 显然,图标部分是因为此时尚未构建图标部分。

heat.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
        xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
        xmlns="http://schemas.microsoft.com/wix/2006/wi">

<xsl:output method="xml" indent="yes"/>

<xsl:param name="pManufacturer" select="'Me'"/>
<xsl:param name="pName" select="'MyApp'"/>
<xsl:param name="pVersion" select="'0.0.0.1'"/>
<xsl:param name="pPackageDesc" select="'My application'"/>
<xsl:param name="pPackageComment" select="'My application'"/>
<xsl:param name="pExeName" select="'4DIAC-IDE.exe'"/>
<xsl:param name="pCabName" select="'MyInstall.cab'"/>

<!-- copy all to output -->
<xsl:template match="@*|*">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates select="*" />
    </xsl:copy>
</xsl:template>

<!-- Ignore svn directories -->
<xsl:template match="wix:Directory[@Name='.svn']" />
<!-- Create searches for the directories to remove. -->
<xsl:key name="svn-search" match="wix:Directory[@Name = '.svn']" use="@Id" />
<!-- Remove components referencing those directories -->
<xsl:template match="wix:Component[key('svn-search', @Directory)]" />

<!-- Set manufacturer attribute -->
<xsl:template match="wix:Product/@Manufacturer">
    <xsl:attribute name="Manufacturer"><xsl:value-of select="$pManufacturer"/></xsl:attribute>
</xsl:template>

<!-- Set product name attribute -->
<xsl:template match="wix:Product/@Name">
    <xsl:attribute name="Name"><xsl:value-of select="$pName"/></xsl:attribute>
</xsl:template>

<!-- Set product version attribute -->
<xsl:template match="wix:Product/@Version">
    <xsl:attribute name="Version"><xsl:value-of select="$pVersion"/></xsl:attribute>
</xsl:template>

<!-- Add description and comments attributes to package element -->
<xsl:template match="wix:Package">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="Description"><xsl:value-of select="$pPackageDesc"/></xsl:attribute>
        <xsl:attribute name="Comments"><xsl:value-of select="$pPackageComment"/></xsl:attribute>
        <xsl:attribute name="InstallerVersion">200</xsl:attribute>
        <xsl:attribute name="Compressed">yes</xsl:attribute>
    </xsl:copy>
</xsl:template>

<!-- Set media element -->
<xsl:template match="wix:Media">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:attribute name="Id">1</xsl:attribute>
        <xsl:attribute name="Cabinet"><xsl:value-of select="$pCabName"/></xsl:attribute>
        <xsl:attribute name="EmbedCab">yes</xsl:attribute>
        <xsl:copy-of select="node()"/>
    </xsl:copy>
</xsl:template>

<!-- Set default feature element -->
<xsl:template match="wix:Feature">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="Id">DefaultFeature</xsl:attribute>
        <xsl:attribute name="Level">1</xsl:attribute>
        <xsl:attribute name="Title">Main Feature</xsl:attribute>

        <!-- Set component references -->
        <!-- TODO is this necessary? -->
        <xsl:element name="ComponentRef">
            <xsl:attribute name="Id">EXE_FILE</xsl:attribute>
        </xsl:element>
        <!-- 
        <xsl:element name="ComponentRef">
            <xsl:attribute name="Id">StartMenuShortcuts</xsl:attribute>
        </xsl:element>
        -->
    </xsl:copy>
</xsl:template>

<!-- Add DesktopFolder and ProgramMenuDir -->
<!-- FIXME ***********************************************************
     When this template is used, the name attribute for each file does not get added
     and therefore neither do the shortcuts.
     Refer to match File template below.
<xsl:template match="wix:Directory">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="@Id='TARGETDIR'">
                <xsl:apply-templates select="@*"/>
                <xsl:copy-of select="node()"/>

                <xsl:element name="Directory">
                    <xsl:attribute name="Id">DesktopFolder</xsl:attribute>
                </xsl:element>
                <xsl:element name="Directory">
                    <xsl:attribute name="Id">ProgramMenuDir</xsl:attribute>
                    <xsl:attribute name="Name"><xsl:value-of select="$pManufacturer"/></xsl:attribute>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="@*"/>
                <xsl:copy-of select="node()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>
-->

<!-- Add icons to product element -->
<!-- FIXME ***********************************************************
     When this template is used, the placeholder "PUT-FEATURE-TITLE-HERE" appears instead of my feature element,
     and the name attribute for each file is not output.
<xsl:template match="wix:Product">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:copy-of select="node()"/>

        <Icon Id="DesktopIcon.exe" SourceFile="$(var.AppSource)\$pExeName" />
        <Icon Id="StartMenuIcon.exe" SourceFile="$(var.AppSource)\$pExeName" />
    </xsl:copy>
</xsl:template>
-->

<!-- Find our executable file and set shortcuts for desktop and program menu -->
<!-- TODO can heat generate Name attribute? -->
<xsl:template match="wix:File">

    <!-- Get file name from Source attribute -->
    <xsl:variable name="fileName">
        <xsl:call-template name="fileNameFromPath">
            <xsl:with-param name="path" select="@Source"/>
        </xsl:call-template>
    </xsl:variable>

    <!-- Add Name attribute to File -->
    <xsl:copy>
        <xsl:attribute name="Name"><xsl:value-of select="$fileName"/></xsl:attribute>
        <xsl:apply-templates select="@*"/>

        <xsl:if test="$fileName=$pExeName">
            <!-- Set Id to match ComponentRef -->
            <xsl:attribute name="Id">EXE_FILE</xsl:attribute>
            <!-- Add application shortcuts -->
            <xsl:element name="Shortcut">
                <xsl:attribute name="Id">desktopShortcut</xsl:attribute>
                <xsl:attribute name="Directory">DesktopFolder</xsl:attribute>
                <xsl:attribute name="Name"><xsl:value-of select="$pName"/></xsl:attribute>
                <xsl:attribute name="WorkingDirectory">INSTALLDIR</xsl:attribute>
                <xsl:attribute name="Advertise">yes</xsl:attribute>
                <xsl:attribute name="Icon">DesktopIcon.exe</xsl:attribute>
                <xsl:attribute name="IconIndex">0</xsl:attribute>
            </xsl:element>
            <xsl:element name="Shortcut">
                <xsl:attribute name="Id">ExeShortcut</xsl:attribute>
                <xsl:attribute name="Directory">ProgramMenuDir</xsl:attribute>
                <xsl:attribute name="Name"><xsl:value-of select="$pName"/></xsl:attribute>
                <xsl:attribute name="WorkingDirectory">INSTALLDIR</xsl:attribute>
                <xsl:attribute name="Advertise">yes</xsl:attribute>
                <xsl:attribute name="Icon">StartMenuIcon.exe</xsl:attribute>
                <xsl:attribute name="IconIndex">0</xsl:attribute>
            </xsl:element>
        </xsl:if>
    </xsl:copy>
</xsl:template>

<!-- template to get file name from path -->
<xsl:template name="fileNameFromPath">
    <xsl:param name="path" />
    <xsl:choose>
        <xsl:when test="contains($path,'\')">
            <xsl:call-template name="fileNameFromPath">
                <xsl:with-param name="path" select="substring-after($path,'\')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="contains($path,'/')">
            <xsl:call-template name="fileNameFromPath">
                <xsl:with-param name="path" select="substring-after($path,'/')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$path" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

当前wxs输出文件的相关部分是:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{A0953F8D-5F10-47A4-BF70-A2B68B6399D8}" Language="1033" Manufacturer="Me" Name="MyApp" UpgradeCode="{EAF31C16-363E-42E8-9110-4EB3ACE2CB32}" Version="0.0.0.1">
    <Package Description="My application" Comments="My application" InstallerVersion="200" Compressed="yes" />
    <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="dirDE09E8843EFC6098356C132F8C772506" Name="MyBase">
            <Directory Id="dirBA2DB469295E757A153AE4E941866015" Name="MyApp">
                <Component Id="cmp6F02BEBF925E45E085A43C8E9129B40A" Guid="*">
                    <File Name=".eclipseproduct" Id="fil5C63854A4E335C543D7ECE7BB88B2658" KeyPath="yes" Source="$(var.AppSource)\MyApp\.eclipseproduct" />
                </Component>
                <Component Id="cmpC186B297004F1D5F5F25B295B20B89A3" Guid="*">
                    <File Name="4DIAC-IDE.exe" KeyPath="yes" Source="$(var.AppSource)\MyApp\4DIAC-IDE.exe" Id="EXE_FILE">
                        <Shortcut Id="desktopShortcut" Directory="DesktopFolder" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="DesktopIcon.exe" IconIndex="0" />
                        <Shortcut Id="ExeShortcut" Directory="ProgramMenuDir" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="StartMenuIcon.exe" IconIndex="0" />
                    </File>
                </Component>

                ...

            </Directory>
        </Directory>
    </Directory>
    <Feature Id="DefaultFeature" Level="1" Title="Main Feature">
        <ComponentRef Id="EXE_FILE" />
    </Feature>
    <Media Id="1" Cabinet="MyInstall.cab" EmbedCab="yes" />
</Product>
</Wix>

通过wixedit手动生成的所需/类似相关部分是:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="6298B282-F405-4AD8-9858-649B832A2AED" Name="MyApp" Language="1033" Version="0.0.0.1" Manufacturer="Me" UpgradeCode="932EE819-799F-4A71-B0A9-7CC8128228E5">
    <Package Description="My application" Comments="My application" InstallerVersion="200" Compressed="yes" />
    <Media Id="1" Cabinet="MyInstall.cab" EmbedCab="yes" />
    <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder" Name="PFiles">
            <Directory Id="Lee" Name="Lee">
                <Directory Id="MyApp" Name="MyApp">
                    <Component Id="_.ECLIPSEPRODUCT" DiskId="1" Guid="AE456466-489C-4A83-BD1A-E4867B657E27">
                        <File Id="_.ECLIPSEPRODUCT" Name=".eclipseproduct" Source="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\.eclipseproduct" />
                    </Component>
                    <Component Id="_4DIAC_IDE.EXE" DiskId="1" Guid="4E3A8845-E606-45D2-8C48-B6119B7F4D8C">
                        <File Id="_4DIAC_IDE.EXE" Name="4DIAC-IDE.exe" Source="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe">
                            <Shortcut Id="desktopShortcut" Directory="DesktopFolder" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="DesktopIcon.exe" IconIndex="0" />
                            <Shortcut Id="ExeShortcut" Directory="ProgramMenuDir" Name="MyApp" Advertise="yes" Icon="StartMenuIcon.exe" IconIndex="0" />
                        </File>
                    </Component>
    ...

    </Directory>
    <Feature Id="DefaultFeature" Title="Main Feature" Level="1">
        <ComponentRef Id="_.ECLIPSEPRODUCT" />
        <ComponentRef Id="_4DIAC_IDE.EXE" />
        ...
    </Feature>
    <UI />
    <UIRef Id="WixUI_Minimal" />
    <Icon Id="DesktopIcon.exe" SourceFile="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe" />
    <Icon Id="StartMenuIcon.exe" SourceFile="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe" />
</Product>
</Wix>

注意Product中的Icon元素,以及_4DIAC_IDE.EXE ComponentRef引用应用程序可执行文件组件中的Id。

因为heat生成XML并应用转换,所以没有输入XML可供查看。然而,在不应用变换的情况下运行热量会产生:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{097247DB-DD4A-4C8D-AF04-75A79143ABCD}" Language="1033" Manufacturer="PUT-COMPANY-NAME-HERE" Name="PUT-PRODUCT-NAME-HERE" UpgradeCode="{73482F22-9A23-4D02-8661-388599DC37A8}" Version="1.0.0.0">
    <Package Compressed="yes" InstallerVersion="200" />
    <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="dirDE09E8843EFC6098356C132F8C772506" Name="Lee">
            <Directory Id="dirBA2DB469295E757A153AE4E941866015" Name="MyApp">
                <Component Id="cmp6F02BEBF925E45E085A43C8E9129B40A" Guid="*">
                    <File Id="fil5C63854A4E335C543D7ECE7BB88B2658" KeyPath="yes" Source="$(var.AppSource)\MyApp\.eclipseproduct" />
                </Component>
                <Component Id="cmpC186B297004F1D5F5F25B295B20B89A3" Guid="*">
                    <File Id="filBE7304CBAC53C43B9DD86ED19DDD2E5E" KeyPath="yes" Source="$(var.AppSource)\MyApp\4DIAC-IDE.exe" />
                </Component>

                ...


      </Directory>
    <Feature Id="ProductFeature" Level="1" Title="PUT-FEATURE-TITLE-HERE" />
    <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
</Product>
</Wix>

0 个答案:

没有答案