Msbuild 如何对具有相同文件的目录加热目录2次或更多次?

Msbuild 如何对具有相同文件的目录加热目录2次或更多次?,msbuild,wix,wix3.5,Msbuild,Wix,Wix3.5,我一直在使用BeforeBuild目标中WiX安装程序项目中的HeatDirectory任务来获取我们部署在客户端网络上的web应用程序的文件。一直工作得很好 现在我想部署第二组文件,这恰好是一些文档,其中包含与前一个HeatDirectory输出中存在的文件同名的文件 我得到以下错误: LGHT0293: Multiple files with ID 'Web.Config' exist. 我明白我为什么会出错,我想知道如何最好地解决它 选项A: 将所有文件复制到一个目录中,并在一次大规模传

我一直在使用BeforeBuild目标中WiX安装程序项目中的HeatDirectory任务来获取我们部署在客户端网络上的web应用程序的文件。一直工作得很好

现在我想部署第二组文件,这恰好是一些文档,其中包含与前一个HeatDirectory输出中存在的文件同名的文件

我得到以下错误:

LGHT0293: Multiple files with ID 'Web.Config' exist.
我明白我为什么会出错,我想知道如何最好地解决它

选项A

将所有文件复制到一个目录中,并在一次大规模传递中对其进行热处理

我喜欢这样,因为使用stock MSBuild任务实现起来相当容易。我不喜欢它,因为它会创建一个庞大的组件组,如果我决定制作可选功能(比如不安装某些东西),我就不能

选项B

迭代HeatDirectory任务的输出文件,并在所有组件ID和文件ID上附加后缀。示例-web.config将变成web.config\u DocumenationFiles

我喜欢这个,因为它很干净;i、 我可以稍后删除它,或者将它添加到有问题的项目中,而不是添加到没有问题的项目中。我不喜欢它,因为我不确定什么“进程”(或MSBuild任务)能够做到这一点。我想我需要一个自定义任务

其他选项

想法?

任务具有
转换
属性,可用于转换结果文件。您可以创建一个xslt,将后缀添加到组件ID中


而且,热是有害的。您可能需要考虑创建自己的收割机,为您的组件ID添加后缀。

我看到有人在三年后对此进行了投票。我想我会回来声明我仍然在使用选项B,一个自定义MSBuild任务来解决这个问题

我对这个问题做了更详细的解释,并认为我应该将我的实现移到这里/复制到这里,以防它有所帮助

我已经解决了这个问题,创建了一个自定义的构建任务,在HeatDirectory任务之后运行,为Id属性添加一个后缀

<AddSuffixToHeatDirectory File="ReportFiles.Generated.wxs" Suffix="_r" />

AddSuffixToHeatDirectory任务就是这样的

public class AddSuffixToHeatDirectory : Task
{
    public override bool Execute()
    {
        bool result = true;

        Log.LogMessage("Opening file '{0}'.", File);
        var document = XElement.Load(File);

        var defaultNamespace = GetDefaultNamespace(document);

        AddSuffixToAttribute(document, defaultNamespace, "Component", "Id");
        AddSuffixToAttribute(document, defaultNamespace, "File", "Id");
        AddSuffixToAttribute(document, defaultNamespace, "ComponentRef", "Id");
        AddSuffixToAttribute(document, defaultNamespace, "Directory", "Id");

        var files = (from x in document.Descendants(defaultNamespace.GetName("File")) select x).ToList();

        Log.LogMessage("Saving file '{0}'.", File);
        document.Save(File);

        return result;
    }

    private void AddSuffixToAttribute(XElement xml, XNamespace defaultNamespace, string elementName, string attributeName)
    {
        var items = (from x in xml.Descendants(defaultNamespace.GetName(elementName)) select x).ToList();
        foreach (var item in items)
        {
            var attribute = item.Attribute(attributeName);
            attribute.Value = string.Format("{0}{1}", attribute.Value, Suffix);
        }
    }

    private XNamespace GetDefaultNamespace(XElement root)
    {
        // I pieced together this query from hanselman's post.
        //  http://www.hanselman.com/blog/GetNamespacesFromAnXMLDocumentWithXPathDocumentAndLINQToXML.aspx
        // 
        // Basically I'm just getting the namespace that doesn't have a localname.
        var result = root.Attributes()
                        .Where(a => a.IsNamespaceDeclaration)
                        .GroupBy(a => a.Name.Namespace == XNamespace.None ? String.Empty : a.Name.LocalName, a => XNamespace.Get(a.Value))
                        .ToDictionary(g => g.Key, g => g.First());
        return result[string.Empty];
    }

    /// <summary>
    /// File to modify.
    /// </summary>
    [Required]
    public string File { get; set; }

    /// <summary>
    /// Suffix to append.
    /// </summary>
    [Required]
    public string Suffix { get; set; }
}
public类AddSuffixToHeatDirectory:任务
{
公共重写bool Execute()
{
布尔结果=真;
LogMessage(“正在打开文件“{0}.”,文件);
var document=XElement.Load(文件);
var defaultNamespace=GetDefaultNamespace(文档);
AddSulfExtoAttribute(文档,默认名称空间,“组件”,“Id”);
AddSuffixToAttribute(文档,默认名称空间,“文件”,“Id”);
AddSuffExtoAttribute(文档,默认名称空间,“ComponentRef”,“Id”);
AddSuffixToAttribute(文档,默认名称空间,“目录”,“Id”);
var files=(从document.subjects(defaultNamespace.GetName(“文件”)中的x选择x).ToList();
LogMessage(“正在保存文件“{0}.”,文件);
文件保存(文件);
返回结果;
}
私有void addSulfExtoAttribute(XElement xml、XNamespace defaultNamespace、string elementName、string attributeName)
{
var items=(从xml.subjects(defaultNamespace.GetName(elementName))中的x选择x.ToList();
foreach(项目中的var项目)
{
var属性=item.attribute(attributeName);
attribute.Value=string.Format(“{0}{1}”,attribute.Value,后缀);
}
}
私有XNamespace GetDefaultNamespace(XElement根目录)
{
//我从hanselman的帖子中拼凑了这个问题。
//  http://www.hanselman.com/blog/GetNamespacesFromAnXMLDocumentWithXPathDocumentAndLINQToXML.aspx
// 
//基本上,我只是得到一个没有localname的名称空间。
var result=root.Attributes()
.Where(a=>a.isNamespace声明)
.GroupBy(a=>a.Name.Namespace==XNamespace.None?String.Empty:a.Name.LocalName,a=>XNamespace.Get(a.Value))
.ToDictionary(g=>g.Key,g=>g.First());
返回结果[string.Empty];
}
/// 
///要修改的文件。
/// 
[必需]
公共字符串文件{get;set;}
/// 
///要附加的后缀。
/// 
[必需]
公共字符串后缀{get;set;}
}

希望有帮助。我今天仍在使用这种方法,我还没有做过研究转换或扩展HeatDirectory的准备工作。

我喜欢这个想法。由于我提出了这个问题,我创建了一个自定义MSBuild任务来“修复”WiX片段文件并附加后缀,但这需要在生成计算机和使用该项目的任何开发人员计算机上安装自定义MSBuild任务。我将首先研究转换和XSLT。