【问题标题】:Create single wix installer for two visual studio projects为两个 Visual Studio 项目创建单个 wix 安装程序
【发布时间】:2014-02-21 14:08:47
【问题描述】:

我正在使用 heat.exe 在构建后事件中使用此脚本来获取我的 Visual Studio 项目的调试(或发布)目录:

call "C:\Program Files (x86)\WiX Toolset v3.8\bin\heat.exe" dir "$(TargetDir)." -var var.WixDemo.TargetDir -dr INSTALLFOLDER -cg Binaries -ag -scom -sreg -sfrag -srd -o "$(SolutionDir)WixSetup\$(ProjectName).Binaries.wxs"

我会得到一个具有两个功能的安装程序:

  1. 项目A

  2. 项目B

问题在于这两个项目引用了同一个 dll (xyz.dll),因此,两个收获进程都为此文件创建了一个具有相同 ID 的组件。


编辑

这是我收获发布目录后的输出文件。

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Directory Id="dir325E6775ACBC3561D5CA2F51CFCCC7E8" Name="WixDemoFeature1">
                <Component Id="cmp22AE0957A805CEDAC8D05EF04AE18D5E" Guid="*">
                    <File Id="fil9EDCA091AB8E6440E9D83A815255C794" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\xyz.dll" />
                </Component>
                <Component Id="cmpFCBDB8083076AA83E1B67540ADFECC9D" Guid="*">
                    <File Id="filAA36C3D42B58D430C889BE47087CA911" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\WixDemoFeature1.exe" />
                </Component>
                <Component Id="cmp8BCDCA87324BD346D955DDB4318E80BD" Guid="*">
                    <File Id="fil69700DBD0795710A0AE5DC17574128D5" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\WixDemoFeature1.exe.config" />
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="WixDemoFeature1Binaries">
            <ComponentRef Id="cmp22AE0957A805CEDAC8D05EF04AE18D5E" />
            <ComponentRef Id="cmpE0CAA29B7BB706D56252E85F7C1DDD0A" />
            <ComponentRef Id="cmp8BCDCA87324BD346D955DDB4318E80BD" />
        </ComponentGroup>
    </Fragment>
</Wix>

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Directory Id="dir325E6775ACBC3561D5CA2F51CFCCC7E8" Name="WixDemoFeature2">
                <Component Id="cmp22AE0957A805CEDAC8D05EF04AE18D5E" Guid="*">
                    <File Id="fil9EDCA091AB8E6440E9D83A815255C794" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\xyz.dll" />
                </Component>
                <Component Id="cmpE0CAA29B7BB706D56252E85F7C1DDD0A" Guid="*">
                    <File Id="fil3A3B754D2B216E86025902C3A826545D" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\WixDemoFeature2.exe" />
                </Component>
                <Component Id="cmpFB159630D6E1604557E20776A46EB6B3" Guid="*">
                    <File Id="fil060CF132A168E46D3C4C1C24CA1AEFF4" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\WixDemoFeature2.exe.config" />
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="WixDemoFeature2Binaries">
            <ComponentRef Id="cmp22AE0957A805CEDAC8D05EF04AE18D5E" />
            <ComponentRef Id="cmpFCBDB8083076AA83E1B67540ADFECC9D" />
            <ComponentRef Id="cmpFB159630D6E1604557E20776A46EB6B3" />
        </ComponentGroup>
    </Fragment>
</Wix>

这两个 xml 组件“xyz.dll”的 ID 相同,因此我不能在 Product.wxs 中同时使用“WixDemoFeature1Binaries”和“WixDemoFeature2Binaries”。

我想要这些:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Directory Id="dir325E6775ACBC3561D5CA2F51CFCCC7E8" Name="WixDemoFeature1">
                <Component Id="cmp_WixDemoFeature1.xyz.dll" Guid="*">
                    <File Id="fil_WixDemoFeature1.xyz.dll" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\xyz.dll" />
                </Component>
                <Component Id="cmp_WixDemoFeature1.WixDemoFeature1.exe" Guid="*">
                    <File Id="fil_WixDemoFeature1.WixDemoFeature1.exe" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\WixDemoFeature1.exe" />
                </Component>
                <Component Id="cmp_WixDemoFeature1.WixDemoFeature1.exe.config" Guid="*">
                    <File Id="fil_WixDemoFeature1.WixDemoFeature1.exe.config" KeyPath="yes" Source="$(var.WixDemoFeature1.TargetDir)\WixDemoFeature1.exe.config" />
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="WixDemoFeature1Binaries">
            <ComponentRef Id="cmp_WixDemoFeature1.xyz.dll" />
            <ComponentRef Id="cmp_WixDemoFeature1.WixDemoFeature1.exe" />
            <ComponentRef Id="cmp_WixDemoFeature1.WixDemoFeature1.exe.config" />
        </ComponentGroup>
    </Fragment>
</Wix>

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Directory Id="dir325E6775ACBC3561D5CA2F51CFCCC7E8" Name="WixDemoFeature2">
                <Component Id="cmp_WixDemoFeature2.xyz.dll" Guid="*">
                    <File Id="fil_WixDemoFeature2.xyz.dll" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\xyz.dll" />
                </Component>
                <Component Id="cmp_WixDemoFeature2.WixDemoFeature2.exe" Guid="*">
                    <File Id="fil_WixDemoFeature2.WixDemoFeature2.exe" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\WixDemoFeature2.exe" />
                </Component>
                <Component Id="cmp_WixDemoFeature2.WixDemoFeature2.exe.config" Guid="*">
                    <File Id="fil_WixDemoFeature2.WixDemoFeature2.exe.config" KeyPath="yes" Source="$(var.WixDemoFeature2.TargetDir)\WixDemoFeature2.exe.config" />
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="WixDemoFeature2Binaries">
            <ComponentRef Id="cmp_WixDemoFeature2.xyz.dll" />
            <ComponentRef Id="cmp_WixDemoFeature2.WixDemoFeature2.exe" />
            <ComponentRef Id="cmp_WixDemoFeature2.WixDemoFeature2.exe.config" />
        </ComponentGroup>
    </Fragment>
</Wix>

如何改变这种行为?

【问题讨论】:

    标签: visual-studio-2010 wix installation heat


    【解决方案1】:

    目标目录是为在开发者机器上调试而设计的,而不是为了收集要打包的文件。

    尽管如此,您有几个选择,包括:

    • Heat 在发出 .wxs 文件之前接受要应用的 XSL 转换。使用 XSL,您可以过滤掉不需要的 Component 和 ComponentRef 元素。
    • 在 WiXSetup 中为项目 A 和项目 B 使用 project reference,并在它们的输出中使用 harvest。然后,您必须单独获取 xyz.dll 或为它手写一个组件。手动创建两个特征并在两者中引用 xyz 组件。 (我假设 WiXSetup 是从 WiX 设置项目模板创建的 Visual Studio 项目。)
    • 使用 MSBuild 的 Copy task 创建您的包布局并收获它。复制任务可以创建硬链接而不是实际复制。 (几乎所有类型的 Visual Studio 项目都是 MSBuild 项目。)

    更新问题的简单 XSLT:

    <?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="http://schemas.microsoft.com/wix/2006/wi"
      exclude-result-prefixes="wix">
      <xsl:output method="xml" indent="yes"/>
    
      <!-- Preserving the order of attributes only for aesthetic reasons -->
    
      <xsl:template match="//wix:Component">
        <xsl:variable name="source" select="wix:File/@Source" />
        <xsl:variable
          name="baseId"
          select="concat(substring-before(substring-after($source, '$(var.'),'.TargetDir)'), 
                  concat('.', substring-after($source,'\')))" />
        <Component>
          <xsl:attribute name="Id">
            <xsl:value-of select="concat('cmp_', $baseId)"/>
          </xsl:attribute>
          <xsl:attribute name="Guid">*</xsl:attribute>
          <File>
            <xsl:attribute name="Id">
              <xsl:value-of select="concat('fil_', $baseId)"/>
            </xsl:attribute>
            <xsl:attribute name="KeyPath">yes</xsl:attribute>
            <xsl:attribute name="Source">
              <xsl:value-of select="wix:File/@Source"/>
            </xsl:attribute>
          </File>
        </Component>
      </xsl:template>
    
      <xsl:template match="//wix:ComponentRef">
        <!-- ComponentRef nodes are interleaved with text() nodes. Want positions 2, 4, 6, ... -->
        <xsl:variable name="index" select="(position() - 1) div 2" /> 
        <xsl:variable name="source" select="//wix:Component[$index]/wix:File/@Source" />
        <xsl:variable
          name="baseId"
          select="concat(substring-before(substring-after($source, '$(var.'),'.TargetDir)'), 
                  concat('.', substring-after($source,'\')))" />
        <ComponentRef>
          <xsl:attribute name="Id">
            <xsl:value-of select="concat('cmp_', $baseId)"/>
          </xsl:attribute>
        </ComponentRef>
      </xsl:template>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 谢谢,我怎样才能使用 XSLT 获得我的目标?再次感谢您。
    • Stack Overflow 不是要求代码的地方,但我无法抗拒kata。下次会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2014-10-04
    • 1970-01-01
    相关资源
    最近更新 更多