如何在Wix工具集中排除文件

try*_*cod 11 wix heat

在为heat.exe收集文件时,我想从输入文件夹中排除扩展名为.exe的文件,因为它首先获取文件夹中的所有文件.

以下是我的代码.

"%WIX_PATH%\ Heat.exe"dir"%input_folder%" - cg SourceProjectComponents -dr INSTALLLOCATION -scom -sreg -srd -var var.BasePath -gg -sfrag -var var.BasePath -out"%output_folder%\ Output. WXS"

PS:input_folder由几个.dll和.exe文件组成.因此无法单独收获文件.

提前致谢.

Bri*_*and 21

您将需要使用XSLT转换.

这样的事情对你有用; 只需-t <Path to the xslt file>在命令行中包含热量即可.

此XSLT输出一个新的XML文件,其中包含输入的所有XML节点,除非任何节点是<Component>具有.exe <File>元素的元素.

RemoveExeComponentsTransform.xslt

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    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"

    version="1.0" 
    exclude-result-prefixes="xsl wix"
>

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

    <xsl:strip-space elements="*" />

    <!--
    Find all <Component> elements with <File> elements with Source="" attributes ending in ".exe" and tag it with the "ExeToRemove" key.

    <Component Id="cmpSYYKP6B1M7WSD5KLEQ7PZW4YLOPYG61L" Directory="INSTALLDIR" Guid="*">
        <File Id="filKUS7ZRMJ0AOKDU6ATYY6IRUSR2ECPDFO" KeyPath="yes" Source="!(wix.StagingAreaPath)\ProofOfPEqualsNP.exe" />
    </Component>

    Because WiX's Heat.exe only supports XSLT 1.0 and not XSLT 2.0 we cannot use `ends-with( haystack, needle )` (e.g. `ends-with( wix:File/@Source, '.exe' )`...
    ...but we can use this longer `substring` expression instead (see https://github.com/wixtoolset/issues/issues/5609 )
    -->
    <xsl:key
        name="ExeToRemove"
        match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 3 ) = '.exe' ]"
        use="@Id"
    /> <!-- Get the last 4 characters of a string using `substring( s, len(s) - 3 )`, it uses -3 and not -4 because XSLT uses 1-based indexes, not 0-based indexes. -->

    <!-- We can also remove .pdb files too, for example: -->
    <xsl:key
        name="PdbToRemove"
        match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 3 ) = '.pdb' ]"
        use="@Id"
    />

    <!-- By default, copy all elements and nodes into the output... -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <!-- ...but if the element has the "ExeToRemove" key then don't render anything (i.e. removing it from the output) -->
    <xsl:template match="*[ self::wix:Component or self::wix:ComponentRef ][ key( 'ExeToRemove', @Id ) ]" />

    <xsl:template match="*[ self::wix:Component or self::wix:ComponentRef ][ key( 'PdbToRemove', @Id ) ]" />

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

  • 这种使用xlst变换进行过滤的方法是如此困难和不直观,以至于它为[Cargo cult](https://en.wikipedia.org/wiki/Cargo_cult_programming)而哭泣. (7认同)
  • 我编辑了这个答案,以使用XSLT 1.0`ends-with`样式匹配,而不是使用`contains(...,'.exe')`,因为否则`app.config`文件(例如`Foo.Bar.exe)。 config`)将被删除,这可能不是您想要的,例如,这将导致绑定重定向被删除(这发生在我身上并且花了很长时间才弄清楚原因!) (2认同)

小智 10

如果您\xe2\x80\x99使用WiX工具集4.0:

\n\n

在设置正确的命名空间 ( ) 之前,xsl 过滤器不会工作。xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"\n我曾经遇到过从 3.11 升级到 4.0 的情况,我花了几个小时才找出过滤器不起作用的原因。无论是在 VS 解决方案中还是在命令行 (heat.exe) 版本中。

\n\n

希望这对某人有帮助

\n


Mur*_*nat 7

我遇到了同样的问题,我有很多文件需要包含到项目中的 WXS 文件中,我编写了一个开源命令行应用程序来生成目录结构、文件和组件的 XML,同时忽略文件夹、扩展名、文件等通过 .wixignore 文件(格式类似于 .gitignore)。

您可以在这里查看它。

  • 就像 Wix 的所有人一样。我仍然不明白它的作用,这不是简单地编写一个程序就容易一百倍。 (17认同)
  • @Michal Hainc,因为在我看来,heat.exe 不太用户友好。 (4认同)

Max*_*nce 5

我喜欢 WiX,但它heat.exe是一种实用程序,使用起来比制作起来更难。您可以编写自己的替代品。您只需枚举目录中的文件,然后输出一些 XML。以下是一些启动跳过 .pdb 文件的代码:

foreach (string file in Directory.EnumerateFiles(directoryName))
{
    string extension = Path.GetExtension(file) ?? "";
    if (extension.Equals(".pdb", OrdinalIgnoreCase)) continue;
    string relativePath = GetRelativePath(wixProjectDirectoryName, file);
    string guid = Guid.NewGuid().ToString("D").ToUpperInvariant();
    stringBuilder.AppendLine($"<Component Id=\"Comp{fileName}\" Guid=\"{guid}\">");
    stringBuilder.AppendLine($"  <File Source=\"{relativePath}\" />");
    stringBuilder.AppendLine("</Component>");
}

public static string GetRelativePath(string baseDirectoryName, string fileFullPath)
{
    string[] absDirs = baseDirectoryName.Split('\\');
    string[] relDirs = fileFullPath.Split('\\');

    int len = absDirs.Length < relDirs.Length
        ? absDirs.Length
        : relDirs.Length;

    int lastCommonRoot = -1;
    int index;

    for (index = 0; index < len; index++)
    {
        if (absDirs[index] == relDirs[index]) lastCommonRoot = index;
        else break;
    }

    if (lastCommonRoot == -1)
        throw new ArgumentException("No common base");

    var relativePath = new StringBuilder();

    for (index = lastCommonRoot + 1; index < absDirs.Length; index++)
    {
        if (absDirs[index].Length > 0) relativePath.Append("..\\");
    }

    for (index = lastCommonRoot + 1; index < relDirs.Length - 1; index++)
        relativePath.Append(relDirs[index] + "\\");
    
    relativePath.Append(relDirs[relDirs.Length - 1]);

    return relativePath.ToString();
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这可能是非常明显的,但最简单的方法是使用 wix 中的预构建事件创建一个仅包含您想要的文件的目录,然后在该目录上运行 heat.exe。