c# - 在 Visual Studio 2013 C# 中更改项目元数据

标签 c# visual-studio-2013 metadata envdte

我有一个用 C# 编写的 Visual Studio 2013 程序包,我需要在其中在运行 Visual Studio 2013 时对 C++ 项目文件中的项目及其属性进行一些更改并拥有该项目加载。其实在保存整个解决方案的时候,保存工程文件也可以。

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="Test">
    <MyItemToChange Include = "TestItem">
      <MyMetadata1ToChange>Value1</MyMetadata1ToChange>
      <MyMetadata2ToChange>Value2</MyMetadata2ToChange>
    </MyItemToChange>
  </ItemGroup>
  <!-- The rest of the file -->
</Project>

在以前的 Visual Studio 版本中,我使用了 Microsoft.Build.Evaluation.Project类来更改项目的项目和元数据。当您有对项目的引用时,您可以直接通过 Project.Xml 属性访问项目的 XML 结构,或者获取不同的 Microsoft.Build.Evaluation.ProjectItem 并使用那里找到的接口(interface)。

但是,由于 Microsoft 在其 2013 版本中更改了 Visual Studio 的结构,尽管 Microsoft.Build.Evaluation.Project 未被弃用,但您无法再通过以下方式访问 C++ 项目Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects因为集合是空的。但是,如果您想访问 C# 项目,它仍然有效。 (事实上​​ ,在调试时深入浏览对象会发现它们仍然使用相同的 Microsoft.Build.Evaluation 命名空间进行内部表示。)

由于我无法再访问 Microsoft.Build.Evaluation.Project,我需要一个替代方法

  1. 访问项目而不是使用 Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects
  2. 在 Visual Studio 2013 运行时编写项目项和元数据。

除非我遗漏了什么,否则以下内容不适合我的目的:

  1. Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetItemAttribute 只为解决方案资源管理器中显示的项目设置属性。 “MyItemToChange”未显示在解决方案资源管理器中
  2. 打开文件并手动编辑和保存它。除非您知道如何抑制 Visual Studio 关于已更改项目的警告以及如何自动重新加载它,否则这不是一个可行的方法。
    注意:您可以关闭解决方案,手动打开项目文件,编辑然后保存并重新打开解决方案。它可以正常工作,数据在那里,除非文件在源代码管理之下。现在它提出了很多新问题(为什么 EnvDTE.DTE.SourceControl.CheckOutItem() 不起作用等)所以我仍然认为如果 Visual Studio 能够处理将数据写入项目文件我会更好。
  3. 反射(reflection)。是的,正如我之前提到的,我可以深入研究内部类以掌握“原始”Microsoft.Build.Evaluation.ProjectMicrosoft.Build.Evaluation.ProjectItem,但首先,它对 future 的使用来说是非常不安全的,据我所知,你不能确定如果你修改这些现在的内部类,项目会知道它是脏的并且必须被保存。

我很高兴有任何建议,因为我真的没有选择了。

谢谢。

最佳答案

好吧,我已经制定了一个解决方法,但不是真正解决问题的方法。

我现在做的是:

  1. 询问用户是否可以关闭整个解决方案并保存所有内容。如果没有,我将取消整个过程:EnvDTE.DTE.ItemOperations.PromptToSave
  2. 尝试让 Visual Studio 2013 使用 EnvDTE.DTE.SourceControl.CheckOutItem() 方法在源代码管理中为我 checkout 项目文件。如果它抛出异常 (NotImplementedException),我会使用一个 bodge 来检查项目文件。也就是说,我使用 Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetProperty() 方法将自定义属性写入项目文件。
  3. 关闭整个解决方案。 EnvDTE.DTE.Solution.Close()
  4. 使用 System.Xml.XmlDocument 类打开项目文件。编辑。节省。哦,并删除我在 2.point 中编写的愚蠢属性(用于强制 Visual Studio 2013 在源代码管理中 checkout 文件的那个。)
  5. 重新打开解决方案。 EnvDTE.DTE.Solution.Open() 此时可能会再次要求用户确认某些源代码控制选项。

为什么它只是一种变通方法而不是合适的解决方案?

  • 。 :)
  • 方法被滥用用于它们不应该使用的东西(将随机属性写入项目只是为了强制源代码控制检查)
  • 如果关闭解决方案/项目不是一个选项,它就不会工作。例如:如果您需要在构建期间或他们正在编辑解决方案/项目/源文件时保存某些内容;或者如果您必须在项目的生命周期内经常这样做而不是一次。

我仍在寻找问题的正确解决方案。但在有人告诉我它是如何完成之前,我必须接受当前的实现。

关于c# - 在 Visual Studio 2013 C# 中更改项目元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22378444/

相关文章:

c# - 在 C# 中运行 MongoDump/MongoRestore

c# - 从 FTP 下载 ZIP 文件并复制到网站内的文件夹

c# - SQLite 1.0.94 未出现在 EDM 提供程序上

gcc - 是否有与 Visual Studio C++ 编译器等效的 -ffast-math 标志

html - 元名称和元属性有什么区别?

video - 如何查找视频 (.AVI .MP4) 的实际录制日期?

c# - 无法访问模型的属性(与模型相比)?

.net - System.IO.Compression Zip 不使用 UTC

php - 如何向图像添加元数据?

c# - 从所有 redis 数据库中获取所有键和值?