internal static void Execute(string targetDirectory, string targetProjectPath, string targetGuid) { // Load up the project into an XDocument XDocument targetProjXml = XDocument.Load(targetProjectPath); // First get the existing Guid of the project string existingProjectGuid = MSBuildUtilities.GetMSBuildProjectGuid(targetProjXml, targetProjectPath); // Now update the project Guid MSBuildUtilities.SetMSBuildProjectGuid(targetProjXml, targetGuid); // Save this file targetProjXml.Save(targetProjectPath); IEnumerable <string> projectsInDirectory = GetProjectsInDirectory(targetDirectory); // First Update All Projects Parallel.ForEach(projectsInDirectory, projectInDirectory => { UpdateProjectReferenceGuids(projectInDirectory, targetProjectPath, existingProjectGuid, targetGuid); }); IEnumerable <string> solutionsInTargetDirectory = GetSolutionsInDirectory(targetDirectory); // Now update Solution Files Parallel.ForEach(solutionsInTargetDirectory, solutionFile => { UpdateSolutionReferenceGuids(solutionFile, targetProjectPath, existingProjectGuid, targetGuid); } ); }
internal static void UpdateProjectReferenceGuids(string pathToProjectToUpdate, string pathToProjectWithNewGuid, string oldGuid, string newGuid) { XDocument projXml = XDocument.Load(pathToProjectToUpdate); // Format the old guid into the expected project format string oldGuidClean = Guid.Parse(oldGuid).ToString("B"); // This will filter to only project references that are really the // target project this is to work around cases where someone has // duplicated the Guid. XElement[] projectReferences = MSBuildUtilities.GetProjectReferenceNodes(projXml) .Where(projectReference => MSBuildUtilities.GetProjectReferenceGUID(projectReference, pathToProjectToUpdate).Equals(oldGuidClean, StringComparison.InvariantCultureIgnoreCase)) .Where(projectReference => { string directoryOfProject = PathUtilities.AddTrailingSlash(Path.GetDirectoryName(pathToProjectToUpdate)); string prIncludeRelative = MSBuildUtilities.GetProjectReferenceIncludeValue(projectReference, pathToProjectToUpdate); string prIncludeExpanded = PathUtilities.ResolveRelativePath(directoryOfProject, prIncludeRelative); return(prIncludeExpanded.Equals(pathToProjectWithNewGuid)); }) .ToArray(); // NOTE: We could just update every single project we find, even if // it was duplicated, but we'll be a sticker about it we should not // have more than a single reference to the same project. if (projectReferences.Length > 1) { string exception = $"Project `{pathToProjectToUpdate}` has more than one reference to project `{pathToProjectWithNewGuid}` this is invalid."; throw new InvalidOperationException(exception); } // Again there should only be 1, but don't bother with First() // incase we change our minds later foreach (XElement projectReference in projectReferences) { MSBuildUtilities.SetProjectReferenceGUID(projectReference, newGuid); } // We need to check the entire string to see if there was any real change bool changesMade = XDocument.Load(pathToProjectToUpdate).ToString() != projXml.ToString(); if (changesMade) { projXml.Save(pathToProjectToUpdate); } }