private static void PerformIntegrateProject(XElement commandElement) { XAttribute attribProject = commandElement.Attribute("project"); XAttribute attribSolution = commandElement.Attribute("solution"); XAttribute attribPluginDir = commandElement.Attribute("pluginDirectory"); string projectFile = (attribProject != null) ? attribProject.Value : null; string solutionFile = (attribSolution != null) ? attribSolution.Value : null; string pluginDirectory = (attribPluginDir != null) ? attribPluginDir.Value : null; string projectRelativeBaseDir = IOHelper.MakePathRelative(".", Path.GetDirectoryName(projectFile)); string solutionRelativeProjectPath = IOHelper.MakePathRelative(projectFile, Path.GetDirectoryName(solutionFile)); Guid projectGuid = Guid.NewGuid(); PrettyPrint.PrintCommand( new PrettyPrint.Element("Integrating", PrettyPrint.ElementType.Command), new PrettyPrint.Element(projectFile, PrettyPrint.ElementType.FilePathArgument), new PrettyPrint.Element("into", PrettyPrint.ElementType.Command), new PrettyPrint.Element(solutionFile, PrettyPrint.ElementType.FilePathArgument)); if (!File.Exists(solutionFile)) { Console.Write("(skip) "); return; } IOHelper.WaitForLockRelease(projectFile, solutionFile); { // Read the project file XDocument csproj = XDocument.Load(projectFile); XElement guidElement = csproj.Root.Descendants("ProjectGuid", true).FirstOrDefault(); if (guidElement != null) { Guid guid; if (Guid.TryParse(guidElement.Value, out guid)) { projectGuid = guid; } } // Set up schedule for elements to remove List <XElement> removeElements = new List <XElement>(); // Remove all elements that have been flagged to not be included in Duality packages foreach (var element in csproj.Descendants("DualityPackageExcludeParentElement", true)) { removeElements.Add(element.Parent); } // Remove all traces of NuGet. Dependencies are handled by Duality Package Management! { // Get rid of packages.config items foreach (var attribute in csproj.Descendants("ItemGroup", true).Elements().Attributes("Include", true)) { if (string.Equals(attribute.Value, "packages.config", StringComparison.InvariantCultureIgnoreCase)) { removeElements.Add(attribute.Parent); } } // Get rid of NuGet imports foreach (var attribute in csproj.Descendants("Import", true).Attributes("Project", true)) { string lowerAttrib = attribute.Value.ToLower(); if (lowerAttrib.Contains(".nuget") || lowerAttrib.Contains("nuget.targets")) { removeElements.Add(attribute.Parent); } } // Get rid of NuGet target data foreach (var attribute in csproj.Descendants("Target", true).Attributes("Name", true)) { string lowerAttrib = attribute.Value.ToLower(); if (lowerAttrib.Contains("EnsureNuGetPackageBuildImports".ToLower())) { removeElements.Add(attribute.Parent); } } } // Transform reference HintPaths to local relative paths foreach (var element in csproj.Descendants("Reference", true).Elements("HintPath", true)) { string assemblyPath = element.Value; string assemblyFileName = Path.GetFileName(assemblyPath); if (File.Exists(assemblyFileName)) { element.Value = Path.Combine(projectRelativeBaseDir, assemblyFileName); } else { foreach (string file in Directory.EnumerateFiles(pluginDirectory, assemblyFileName, SearchOption.AllDirectories)) { element.Value = Path.Combine(projectRelativeBaseDir, file); break; } } } // Transform project references to local relative paths XElement referenceGroup = csproj.Descendants("Reference", true).First().Parent; foreach (var element in csproj.Descendants("ProjectReference", true)) { string projectPath = element.Attribute("Include", true).Value; string assemblyFileName = Path.GetFileNameWithoutExtension(projectPath) + ".dll"; string assemblyPath = null; if (File.Exists(assemblyFileName)) { assemblyPath = assemblyFileName; } else { foreach (string file in Directory.EnumerateFiles(pluginDirectory, assemblyFileName, SearchOption.AllDirectories)) { assemblyPath = file; break; } } if (!string.IsNullOrEmpty(assemblyPath) && File.Exists(assemblyPath)) { XNamespace defaultNs = referenceGroup.Name.Namespace; AssemblyName name = AssemblyName.GetAssemblyName(assemblyPath); referenceGroup.Add(new XElement(defaultNs + "Reference", new XAttribute("Include", name.ToString()), new XElement(defaultNs + "HintPath", Path.Combine(projectRelativeBaseDir, assemblyPath)))); removeElements.Add(element); } } // Remove all elements that were scheduled for removal foreach (var element in removeElements) { element.RemoveUpwards(); } // Add a new post-build step that copies the files string postBuildCommand = "mkdir \"$(SolutionDir)../../Plugins\"" + Environment.NewLine + "copy \"$(TargetPath)\" \"$(SolutionDir)../../Plugins\"" + Environment.NewLine + "xcopy /Y \"$(TargetDir)*.xml\" \"$(SolutionDir)../../Plugins\""; XElement postBuildElement = csproj.Descendants("PostBuildEvent", true).FirstOrDefault(); if (postBuildElement == null) { XNamespace defaultNs = referenceGroup.Name.Namespace; csproj.Root.Add(new XElement(defaultNs + "PropertyGroup", postBuildElement = new XElement(defaultNs + "PostBuildEvent"))); } postBuildElement.Value = (postBuildElement.Value ?? "") + Environment.NewLine + postBuildCommand; // Save the project file and be done with it csproj.Save(projectFile); } // Add the project to the existing solution { List <string> solutionLines = File.ReadAllLines(solutionFile).ToList(); Guid projectTypeGuid = Guid.Parse("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"); // Just to be sure, see if we can extract the project type Guid from existing C# project references. foreach (string line in solutionLines) { string trimmedLine = line.Trim(); if (line.StartsWith("Project(") && line.Contains(".csproj")) { string[] token = line.Split('"'); if (token.Length > 1) { string csprojGuidString = token[1]; Guid guidFromFile; if (Guid.TryParse(csprojGuidString, out guidFromFile)) { projectTypeGuid = guidFromFile; } } } } // Add a new project reference to the solution int projectIndex = solutionLines.LastIndexOf("EndProject"); if (projectIndex == -1) { projectIndex = solutionLines.Count - 1; } solutionLines.Insert(projectIndex + 1, string.Format("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", projectTypeGuid, Path.GetFileNameWithoutExtension(projectFile), solutionRelativeProjectPath, projectGuid)); solutionLines.Insert(projectIndex + 2, "EndProject"); File.WriteAllLines(solutionFile, solutionLines); } }
public static void Main(string[] args) { string updateFilePath = (args.Length >= 1) ? args[0] : null; string runAfterFinishPath = (args.Length >= 2) ? args[1] : null; string runAfterFinishWorkDir = (args.Length >= 3) ? args[2] : null; if (string.IsNullOrEmpty(updateFilePath) || !File.Exists(updateFilePath)) { return; } bool anyErrorOccurred = false; Console.WriteLine(); Console.WriteLine("Waiting for file locks to release..."); Console.WriteLine(); IOHelper.WaitForLockRelease("DualityEditor.exe", "Duality.dll"); Console.WriteLine(); Console.WriteLine("Begin applying update"); Console.WriteLine(); // Retrieve elements and order them XDocument updateDoc = XDocument.Load(updateFilePath); List <CommandInfo> commands = new List <CommandInfo>(); { int elementIndex = 0; foreach (XElement element in updateDoc.Root.Elements()) { commands.Add(new CommandInfo(element, elementIndex)); elementIndex++; } commands.Sort((a, b) => Comparer <int> .Default.Compare(a.SortValue, b.SortValue)); } // Perform operations in order CommandType lastCommandType = CommandType.Unknown; for (int i = 0; i < commands.Count; i++) { CommandInfo command = commands[i]; if (command.Type != lastCommandType) { Console.WriteLine(); } try { switch (command.Type) { case CommandType.Remove: PerformRemove(command.Element); break; case CommandType.Update: PerformUpdate(command.Element); break; case CommandType.IntegrateProject: PerformIntegrateProject(command.Element); break; case CommandType.SeparateProject: PerformSeparateProject(command.Element); break; default: throw new InvalidOperationException(string.Format("Unknown command: {0}", command.Element.Name)); } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("success"); Console.ResetColor(); } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("failed"); Console.WriteLine(); Console.WriteLine("Exception: {0}", e); Console.WriteLine(); Console.ResetColor(); IOHelper.WaitForUserRead(); anyErrorOccurred = true; } lastCommandType = command.Type; } // If an error occurred, abort here if (anyErrorOccurred) { Console.WriteLine(); Console.WriteLine("Some steps of the update process failed. The update was not successfull."); Console.WriteLine(); IOHelper.WaitForUserRead(); return; } File.Delete(updateFilePath); Console.WriteLine(); Console.WriteLine("Update applied."); Console.WriteLine(); if (!string.IsNullOrEmpty(runAfterFinishPath) && File.Exists(runAfterFinishPath)) { Console.WriteLine(); Console.WriteLine("Running scheduled application..."); Console.WriteLine(); ProcessStartInfo startInfo = new ProcessStartInfo(runAfterFinishPath); if (!string.IsNullOrEmpty(runAfterFinishWorkDir) && Directory.Exists(runAfterFinishWorkDir)) { startInfo.WorkingDirectory = runAfterFinishWorkDir; } Process.Start(startInfo); } }