简体   繁体   English

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

[英]Changing Project Metadata in Visual Studio 2013 C#

I've got a Visual Studio 2013 package written in C# where I need to make some changes in the items and their attributes in a C++ project file while Visual Studio 2013 is running and has the project loaded. 我有一个用C#编写的Visual Studio 2013包,我需要在Visual Studio 2013运行并加载项目时对C ++项目文件中的项及其属性进行一些更改 Actually, it could also be OK to save the project file at the point when the whole solution is being saved. 实际上,在保存整个解决方案时保存项目文件也可以。

<?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>

In previous Visual Studio versions I used the Microsoft.Build.Evaluation.Project class to change the items and the metadata of the project. 在以前的Visual Studio版本中,我使用Microsoft.Build.Evaluation.Project类来更改项目的项目和元数据。 When you have the reference to the project, you can either accessed the XML structure of the project directly through Project.Xml property or get a hold on different Microsoft.Build.Evaluation.ProjectItem and use the interfaces found there. 当您拥有对项目的引用时,您可以直接通过Project.Xml属性访问项目的XML结构,或者获取不同的Microsoft.Build.Evaluation.ProjectItem并使用在那里找到的接口。

However, since Microsoft has changed the structure of Visual Studio in their 2013 release, though the Microsoft.Build.Evaluation.Project is not deprecated, you can't access the C++ projects any more through Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects as the collection is empty. 但是,由于Microsoft已在2013版本中更改了Visual Studio的结构,但不推荐使用Microsoft.Build.Evaluation.Project ,因此无法通过Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection访问C ++项目。 LoadedProjects作为集合是空的。 However it still works if you want to access C# projects. 但是,如果要访问C#项目,它仍然有效。 (As a matter of fact, browsing deep into the objects while debugging you can find that they still use the same Microsoft.Build.Evaluation namespace for inner representation.) (事实上​​,在调试时深入浏览对象可以发现它们仍然使用相同的Microsoft.Build.Evaluation命名空间进行内部表示。)

Since I can't access the Microsoft.Build.Evaluation.Project any more, I need an alternative to 由于我无法再访问Microsoft.Build.Evaluation.Project ,我需要替代

  1. access the project otherwise than using the Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects 除了使用Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects之外,访问项目
  2. write project items and metadata while Visual Studio 2013 is running. 在Visual Studio 2013运行时编写项目项和元数据。

Unless I've missed something, the following are not good for my purposes: 除非我错过了什么,否则以下内容对我的目的不利:

  1. Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetItemAttribute sets only attributes to items that are displayed in the Solution Explorer. Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetItemAttribute仅将属性设置为“解决方案资源管理器”中显示的项目。 "MyItemToChange" is not displayed in the Solution Explorer 解决方案资源管理器中不显示“MyItemToChange”
  2. Opening the file and manually editing and saving it. 打开文件并手动编辑并保存。 Unless you know how to suppress Visual Studio's warning about a changed project and how to auto reload it, it is not a way to go. 除非您知道如何抑制Visual Studio对已更改项目的警告以及如何自动重新加载它,否则它不是一种可行的方法。
    Note: You can close the solution, open the project file manually, edit then save it and reopen the solution. 注意: 您可以关闭解决方案,手动打开项目文件,编辑然后保存并重新打开解决方案。 It would work fine, the data is there, unless the files are under source control. 它会正常工作,数据就在那里,除非文件受源代码控制。 Now it opens up a whole lot of new issues (why EnvDTE.DTE.SourceControl.CheckOutItem() doesn't work, etc.) So I still think I would be better off if Visual Studio would handle writing data to the project file. 现在它打开了很多新问题(为什么EnvDTE.DTE.SourceControl.CheckOutItem()不起作用等等。)所以我仍然认为如果Visual Studio将数据写入项目文件,我会更好。
  3. Reflection. 反射。 Yes, as I mentioned before, I could dig into internal classes to get a hold on the "original" Microsoft.Build.Evaluation.Project , and Microsoft.Build.Evaluation.ProjectItem , but first of all, it is quite unsafe for future uses and as far as I remember, you cannot be sure that if you modify these now internal classes, the project will know that it is dirty and has to be saved. 是的,正如我之前提到的,我可以挖掘内部类来获取“原始” Microsoft.Build.Evaluation.ProjectMicrosoft.Build.Evaluation.ProjectItem ,但首先,它对未来非常不安全使用并且据我记得,你不能确定如果你现在修改这些内部类,项目将知道它是脏的并且必须保存。

I'm glad to have any suggestions as I'm really running out of options. 我很高兴有任何建议,因为我真的没有选择。

Thanks. 谢谢。

Well, I have worked out a workaround , not a real solution for the problem. 好吧,我已经找到了解决方法 ,而不是问题的真正解决方案。

What I do right now is the following: 我现在做的是以下内容:

  1. Ask the user whether they're OK with closing the whole solution and saving everything. 询问用户是否可以关闭整个解决方案并保存所有内容。 If not, I cancel the whole procedure: EnvDTE.DTE.ItemOperations.PromptToSave 如果没有,我取消整个过程: EnvDTE.DTE.ItemOperations.PromptToSave
  2. Try to ask Visual Studio 2013 to check out the project file for me in source control using EnvDTE.DTE.SourceControl.CheckOutItem() method. 尝试让Visual Studio 2013使用EnvDTE.DTE.SourceControl.CheckOutItem()方法在源代码管理中检查项目文件。 If it throws an exception (NotImplementedException), I use a bodge to check out the project file. 如果它抛出异常(NotImplementedException),我使用bodge来检查项目文件。 That is, I write a custom property into the project file using Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetProperty() method. 也就是说,我使用Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetProperty()方法将自定义属性写入项目文件。
  3. Close the whole solution. 关闭整个解决方案。 EnvDTE.DTE.Solution.Close()
  4. Open the project file using the System.Xml.XmlDocument class. 使用System.Xml.XmlDocument类打开项目文件。 Edit. 编辑。 Save. 救。 Oh, and remove my silly property written in the 2. point (the one used to force Visual Studio 2013 to check out the file in source control.) 哦,并删除我在2.点(用于强制Visual Studio 2013检查源代码管理中的文件)中的愚蠢属性。
  5. Reopen the solution. 重新打开解决方案。 EnvDTE.DTE.Solution.Open() At this point the user might be asked again to confirm some source control options. EnvDTE.DTE.Solution.Open()此时可能会再次要求用户确认某些源控制选项。

Why is it just a workaround not a proper solution? 为什么它只是一种解决方法而不是一个合适的解决方案

  • It's ugly . 很难看 :) :)
  • Methods are abused for things they are not meant to be used (writing a random property into a project just to force source control checkout) 方法被滥用于他们不打算使用的东西(将随机属性写入项目以强制源控制结账)
  • It wouldn't work if closing the solution / project is not an option. 如果关闭解决方案/项目不是一个选项,它将无法工作。 Eg: if you need to save something during build or while they are editing the solution / project / source files; 例如:如果您需要在构建期间或在编辑解决方案/项目/源文件时保存某些内容; or if you have to do it often not just once during the lifetime of a project. 或者如果你不得不经常在项目的整个生命周期中做一次。

I'm still looking for the proper solution for the problem. 我仍在为这个问题寻找合适的解决方案。 But until someone could tell me how it is done, I have to live with this current implementation. 但是,除非有人能告诉我它是如何完成的,否则我必须忍受当前的实施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM