虽然这是一个老问题,但我今天不得不解决它,所以就算只有一点点价值,我也想分享一下我的解决方法。
首先,据我所知,如果你使用Microsoft.Build.Evaluation更新项目,没有Visual Studio提示用户重新加载,你是无法完成更新的。你必须调用project.Save()
将你的更新写入项目XML文件中,然后Visual Studio会“看到”文件更改并显示提示。
但你可以使用EnvDTE来代替Microsoft.Build.Evaluation,这似乎就是Entity Framework所做的,尽管使用Powershell。EnvDTE可在NuGet上获取,最新版本支持.NET Framework 4.5和.NET Standard 2,因此应该相当兼容。
使用EnvDTE,您可以获取对Project
对象的引用并调用AddFromFile(absoluteFilePath)
- 如果需要,还有其他Add()
方法。
如果您拥有项目的完整文件路径,则可以使用以下方式获取项目文件:
using System.Linq;
using System.Runtime.InteropServices;
using EnvDTE;
var dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE");
var project = dte
.Solution
.EnumerateProjects()
.First(p => p.FullName == fullPathToProject);
...其中EnumerateProjects()
是以下扩展方法:
using EnvDTE;
using System.Collections;
using System.Collections.Generic;
internal static class EnvDteExtensions
{
public static IEnumerable<Project> EnumerateProjects(
this Solution solution)
{
return Enumerate(solution.Projects);
}
private static IEnumerable<Project> Enumerate(IEnumerable items)
{
foreach (var item in items)
{
var candidateProject = item;
if (candidateProject is ProjectItem projectItem &&
projectItem.SubProject != null)
{
candidateProject = projectItem.SubProject;
}
if (!(candidateProject is Project project))
{
continue;
}
yield return project;
try
{
if (project.ProjectItems == null)
{
continue;
}
}
catch
{
continue;
}
foreach (var subProject in Enumerate(project.ProjectItems))
{
yield return subProject;
}
}
}
}
在EnvDTE中,Project
可能实际上是一个项目,也可能是包含项目的解决方案文件夹 - candidateProject is ProjectItem projectItem && projectItem.SubProject != null
检查处理后一种情况。
EnvDTE的Project.AddFromFile()
将文件弹出到解决方案资源管理器中,而不需要重新加载项目。
最后,AddFromFile()
似乎是幂等的,因此您可以将相同的文件重复添加到项目中,而不必担心它是否已经存在。