【问题标题】:How to programmatically make an autogenerated file an embedded resource in visual studio?如何以编程方式使自动生成的文件成为 Visual Studio 中的嵌入式资源?
【发布时间】:2016-01-22 12:10:09
【问题描述】:

我有一个这样复杂的工作流程:在 Visual Studio (2013) 中构建其中一个项目会导致生成 XML 文件。这些文件被另一个项目使用,作为框架的一部分。

但是,为了使 XML 文件有任何用途,它们将被标记为嵌入式资源 - 目前通过文件属性通过 VS UI/表单完成。这对于手动添加的文件很有用。

但是我如何以编程方式使自动生成的 XML 文件成为嵌入式资源,以便下一个项目可以选择它(在某种意义上)并拥有文件嵌入到相应的DLL中?

我目前的猜测是以编程方式编辑.csproj 文件并添加类似于下面的行:

<EmbeddedResource Include="Path\To\File\MyEmbeddedResource.meta.xml" />

是吗?

【问题讨论】:

标签: c# xml visual-studio embedded-resource


【解决方案1】:

您可以使用链接项来实现这一点,并且 - 如果它们都是同一解决方案的一部分 - 一组适当的构建依赖项。

首先,构建项目,以便创建要添加为资源的 XML 文件。

接下来,在要嵌入 XML 的项目中,右键单击解决方案资源管理器中的项目,选择“添加现有”并浏览 XML 文件。在浏览器中点击“添加”按钮之前,单击其右侧的下拉按钮并选择“添加为链接”。这将确保文件始终是当前文件。

选择添加的文件链接并将构建类型更改为“嵌入式资源”。

假设您的 XML 来自同一解决方案中的项目(如果不是,请忽略此位),然后在项目依赖项下的解决方案属性中,您可以将目标项目(资源所在的位置)设置为依赖于源项目构建 XML 文件。

或者,如果您愿意,可以自己添加链接:

<EmbeddedResource Include="Path\To\File\MyEmbeddedResource.meta.xml">
    <Link>MyEmbeddedResource.meta.xml</Link>
</EmbeddedResource>

编辑:经过讨论...

如下面的 cmets 所述,如果您想通过直接操作项目文件来做到这一点,您需要执行以下操作:

  1. 将项目加载为某种 Xml 文档。

  2. 找到包含项目文件列表的ItemGroup节点,这通常是项目中唯一包含至少一个Compile节点的节点。

  3. 对于每个文件,插入一个新的 EmbedResource 节点和一个可选的 Link 节点。 Link 节点不是必需的,但这是您手动添加链接文件时得到的。

  4. 保存文件。

看起来相当简单。我的 Xml 有点生疏,但这段代码产生了我想要的确切输出:

// required 'using' directives: System.IO, System.Xml.Linq

public static void EmbedResourceFiles(string projectFilename, IEnumerable<string> fileList, bool makeLinks = true)
{
    // This is the namespace used by the .csproj Xml file
    XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
    // 1: Open the document
    XDocument project = XDocument.Load(projectFilename);

    // 2: Locate target ItemGroup
    var itemGroup = project.Descendants(ns + "Compile").FirstOrDefault()?.Parent;
    if (itemGroup == null)
        throw new Exception("Failed to locate correct ItemGroup node in project file");

    // 3: Insert EmbedResource nodes
    foreach (var file in fileList)
    {
        var node = new XElement(ns + "EmbeddedResource", new XAttribute("Include", file));
        if (makeLinks)
            node.Add(new XElement(ns + "Link", Path.GetFileName(file)));
        itemGroup.Add(node);
    }

    // 4: Save it, keeping a backup just in case.
    File.Copy(projectFilename, projectFilename + ".bak", true);
    project.Save(projectFilename);
}

根据需要收集文件列表并将列表传递给上述方法。如果您想禁止创建&lt;Link&gt; 节点,请在第三个参数中将其设为“false”。我做了一些测试,这两种方法似乎都没有任何区别。

希望这能解决您的问题。

【讨论】:

  • 我想你误会了。我的意思是以编程方式执行“所有”步骤。没有右键单击和添加项目:)
  • 然后使用我在答案底部包含的&lt;EmbeddedResource...。打开 CSProj 文件,找到包含 &lt;Compile&gt; 节点的 &lt;ItemGroup&gt; 节点,添加或更新所需的 &lt;EmbeddedResource&gt; 节点。手工更简单:)
  • 尝试手动处理 300 多个文件 :)
  • 如果文件位于单个位置(或位于几个位置的组),您可以在 Add Existing Item 文件选择器中一次选择所有文件。这通过文件的统一程度缩短了过程。否则......当我必须构建这样的大列表时,我喜欢在我的最爱文本编辑器中查找/替换正则表达式。
  • 您应该明白 - 如果这些文件是通过编程方式生成的,它们将永远不会位于一个位置。我希望它们被“自动”添加,并且没有任何手动干预。您不能假设诸如“如果文件位于同一位置”之类的事情以及将问题简化为手动解决方案的其他事情。没用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多