Microsoft.Build.Evaluation.Project在VS中添加文件夹和文件强制刷新项目

时间:2015-09-03 16:10:48

标签: c# visual-studio

我正在创建一个应用程序,它会将一些文件和文件夹添加到Visual Studio中加载的现有项目中。这有效,但它总是会弹出一条消息告诉用户(我)刷新项目以显示新文件。

enter image description here

使用Entity Framework并添加迁移时,它会将文件添加到当前加载的项目中,并且不会询问用户。我希望能够做同样的事情。

这可能吗?如果有人不知道答案他们是否知道如何深入研究EF并添加迁移以了解他们是如何做到的?

以下是我用来编辑项目文件的代码:

using Microsoft.Build.Evaluation;

 internal class ProjectFileHandler
    {
        private void AddMigrationFolder(Project project, string     projectFileLocation, string name)
        {
            var loc = Path.Combine(projectFileLocation.Substring(0, projectFileLocation.LastIndexOf("\\")), name);
            project.AddItem("Folder", loc);            
        }

        internal void AddMigrationFile(string projectfileLocation, string migrationFolderName, string fileLocation)
        {
            var project = new Project(projectfileLocation);
            AddMigrationFolder(project, projectfileLocation, migrationFolderName);

            project.AddItem("Compile", fileLocation);

            project.Save();
        }
    }

2 个答案:

答案 0 :(得分:0)

很老了,但我会发表评论。也许它可以帮助别人。

问题是“project.Save();”

解决方案将此视为“外部”变更。 不用这一行就试试你的代码。

答案 1 :(得分:0)

年龄更大了,但我今天必须解决这个问题,所以不管它的价值,这就是我所做的。

首先,据我所知,如果没有 Visual Studio 提示用户重新加载项目,则无法使用 Microsoft.Build.Evaluation 更新项目。您必须调用 project.Save() 将更新写入项目 XML,Visual Studio 会“看到”文件更改并显示提示。

可以做什么 - 这看起来是实体框架所做的,尽管 with Powershell - 是使用 EnvDTE 而不是 Microsoft.Build.Evaluation。 EnvDTE 可用 on 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() 似乎是幂等的,因此您可以将同一个文件垃圾邮件到项目中,而不必担心它是否已经存在。