我一直在BeforeBuild目标中的WiX安装程序项目中使用HeatDirectory任务来收集我们在客户端网络上部署的Web应用程序的文件。工作得很好。
我现在想要部署第二组文件,这恰好是一些文档,它包含与之前的HeatDirectory输出中存在的同名文件。
我收到以下错误:
LGHT0293: Multiple files with ID 'Web.Config' exist.
我理解为什么我会收到错误,我想知道如何最好地解决它。
选项A :
将所有文件复制到一个目录中,并在一次大量传递中对它们进行加热。
我喜欢这个,因为使用库存MSBuild任务实现相当容易。我不喜欢它,因为它会创建一个巨大的ComponentGroup,如果我决定制作可选功能(比如不安装某些东西),我就不能。
选项B :
迭代HeatDirectory任务的输出文件,并在所有组件ID和文件ID上附加后缀。示例 - web.config将成为web.config_DocumenationFiles
我喜欢这个,因为它很干净;即我可以稍后将其删除或将其添加到有问题的项目中,而不是将其添加到不具有该问题的项目中。我不喜欢它,因为我不确定“进程”(或MSBuild任务)能够执行此操作。我认为我需要一个自定义任务。
其他选项:?
想法?
答案 0 :(得分:4)
HeatDirectory任务具有Transforms
属性,您可以使用该属性转换结果文件。您可以创建一个xslt来将后缀添加到组件ID。
此外,热火是extensible。您可能想要创建自己的收割机,为您添加组件ID后缀。
答案 1 :(得分:1)
三年后,我看到有人出现并投票。我以为我会回来说我还在使用Option B,这是一个自定义的MSBuild任务来解决这个问题。
关于这个问题,我提出了a comment on another post更详细的信息,并认为我会在此处移动/复制我的实施,以防它有用。
我通过创建一个自定义构建任务来解决它,以便在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; }
}
希望有所帮助。我今天仍在使用这种方法,而且我没有做过调查变换或扩展HeatDirectory的工作。