1

I'm trying to iteratively (part of automation):

  • Create backup of the projects in solution (physical files on the filesystem)
  • Using Microsoft.Build programmatically load and change projects inside of the solution (refernces, includes, some other properties)
  • Build it with console call of msbuild
  • Restore projects (physically overriding patched versions from backups)

This approach works well for first iteration, but for second it appears that it does not load restored projects and trying to work with values that I patched on the first iteration. It looks like projects are cached: inside of the csproj files I see correct values, but on the code I see previously patched values. My best guess is that Microsoft.Build is caching solution/projects in the context of the current process.

Here is code that is responsible to load project and call method to update project information:

private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
    SolutionFile slnFile = SolutionFile.Parse(slnPath);
        var filtredProjects = slnFile
            .ProjectsInOrder
            .Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);

        foreach (ProjectInSolution projectInfo in filtredProjects)
        {
            try
            {
                ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
                patchProject(project);
                project.Save();
            }
            catch (InvalidProjectFileException ex)
            {
                Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
            }
        }
}
Kiryl
  • 180
  • 13

1 Answers1

0

There is Reload method for the ProjectRootElement that migh be called before iteraction with content of the project. It will enforce Microsoft.Build to read latest information from the file.

Code that is working for me:

private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
    SolutionFile slnFile = SolutionFile.Parse(slnPath);
        var filtredProjects = slnFile
            .ProjectsInOrder
            .Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);

        foreach (ProjectInSolution projectInfo in filtredProjects)
        {
            try
            {
                ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
                project.Reload(false); // Ignore cached state, read actual from the file
                patchProject(project);
                project.Save();
            }
            catch (InvalidProjectFileException ex)
            {
                Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
            }
        }
}

Note: It better to use custom properties inside of the project and provide it for each msbuild call instead of physical project patching. Please consider it as better solution and use it if possible.

Kiryl
  • 180
  • 13