48

背景

我正在制作一个帮助应用程序,它重新格式化一些代码文件并创建新的代码文件,这些文件将被添加到我的另一个项目中,所以我可以立即使用新代码,但是我在添加新代码文件时遇到了严重问题自动进入我的项目。顺便说一句,它在 c# 中,帮助应用程序是 WinForms。

失败的尝试

这个问题的唯一答案有两种方法可以做到这一点,但我无法让它们中的任何一个起作用。第一个我找不到Microsoft.Build要引用的程序集,而另一个显然没有足够的命令行参数。

问题

如何在不使用第三方应用程序的情况下以编程方式将文件包含到项目中?

基本上,我正在寻找这样的等价物:

...但是使用代码完成。

要求

这些是我认为解决方案应该提供的功能:

  • 选择包含我们要添加文件的项目的解决方案
  • 选择要添加文件的项目
  • 选择项目中的目录
  • 当然,我们要添加的文件

进步

在用户@psubsee2003 的帮助下,我能够在我的计算机上的文件夹中找到该Microsoft.Build.dll文件,并通过将我的项目的目标框架更改为版本 4 Full profileC:\Windows\Microsoft.NET\Framework\v4.0.30319而成功导入它,而不是默认的客户端配置文件。

我发现了如何使用该AddItem方法:

var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\MyProject.csproj");
p.AddItem("Compile", @"C:\folder\file.cs");
p.Save();

该文件将出现在项目的根文件夹中,除非该项目已经有一个名为 的文件夹folder,在这种情况下,该文件将被放置在那里。因此,基本上该文件将放置在原始文件路径中指向根文件夹的最深文件夹链中。

4

6 回答 6

33

它适用于我只是将它添加到 ProjectFolder 中,并且还像这样以编程方式添加文件夹。

var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\BabDb\test\test.csproj");
        p.AddItem("Folder", @"C:\projects\BabDb\test\test2");
        p.AddItem("Compile", @"C:\projects\BabDb\test\test2\Class1.cs");
        p.Save();
于 2014-05-08T08:49:57.823 回答
14

作为 Boot750 答案的补充(最初建议作为对他的答案的编辑,但作为独立版本重新发布)

您应该注意,调用new Microsoft.Build.Evaluation.Project(path)实际上会导致项目被加载到Microsoft.Build.Evaluation程序集维护的全局缓存中。使用相同的路径再次调用new Project(path),而不首先从全局集合中卸载它/重新启动您的应用程序将导致如下异常:

项目集合中已存在等效项目(具有相同全局属性和工具版本的项目),路径为“YOUR_PATH”。要将等效项加载到此项目集合中,请先卸载此项目。

即使变量p已经超出范围。

因此,如果您打算重复使用 Load/AddItem/Save 模式,您可能需要采用更像这样的模式:

 var p =
Microsoft.Build.Evaluation
  .ProjectCollection.GlobalProjectCollection
    .LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);

if (p == null)
   p = new Microsoft.Build.Evaluation.Project(projFilePath);
于 2017-06-29T17:06:48.327 回答
8

只是为了添加来自@caius-jard 的回复

一旦项目位于 GlobalProjectCollection 中,它就会保存在内存中,并且不会反映对项目所做的任何手动更改。这包括更新 .csproj 文件和使用 VS 删除生成的文件。

如果您删除生成的文件并再次运行代码,项目将更新为包含 2 个生成的文件。在使用之前使用 ReevaluateIfNecessary() 函数更新项目的实例,如下所示:

var p = Microsoft.Build.Evaluation
        .ProjectCollection.GlobalProjectCollection
        .LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);

if (p == null)
    p = new Microsoft.Build.Evaluation.Project(projFilePath);

// Update instance of project
p.ReevaluateIfNecessary();

// Check folder is not already in the project
var folderLoc = @"C:\projects\BabDb\test\test2";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == folderLoc) == null)
    p.AddItem("Folder", folderLoc);

// Check file is not already in the project
var fileLoc = @"C:\projects\BabDb\test\test2\Class1.cs";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == fileLoc) == null)
    p.AddItem("Compile", fileLoc);

p.Save();
于 2017-09-12T08:05:14.197 回答
7

最简单的方法是修改项目文件。由于它只是一个 MSBUILD 文件,VS 将获取更改并提示重新加载项目。将项目文件加载为 XML 并找到第一个<Compile Include="Name of File.cs" />. 插入一个新的<Compile Include="NewFile.CS" />,你就完成了。

作为另一种选择,您可以删除所有<Compile>标签并将其替换为<Compile Include="*.cs" />

于 2014-05-05T19:16:47.640 回答
1

我知道这是一个旧帖子。但是,我需要这个选项并且没有找到我希望的合适的选项。因此,我开发了一个具有扩展功能的 VS 扩展。您可以设置文件类型,然后选择项目目录列表,您希望它们的文件在生成后加载到项目中。

市场(免费) | 源代码

于 2019-11-29T01:39:11.580 回答
-1

您可以使用 T4 文本模板。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/vstudio/bb126445(v=vs.100).aspx

于 2013-09-10T18:11:43.873 回答