private async Task InjectBaseConfigWarningComment(string baseConfigFullPath) { var xml = new XmlDocument(); xml.Load(baseConfigFullPath); var commentXml = string.Format(@" !! WARNING !! Do not modify the {0}.config file directly. Always edit the configurations in - {1}\{0}.{2}.config - {1}\{0}.[Debug|Release].config ", ProjectProperties.AppCfgType, ProjectProperties.ConfigDir, ProjectProperties.CfgBaseName); var commentXmlNode = xml.CreateComment(commentXml); Debug.Assert(xml.DocumentElement != null, "xml.DocumentElement != null"); if (xml.DocumentElement.ChildNodes.Count > 0) { xml.DocumentElement.InsertBefore(commentXmlNode, xml.DocumentElement.FirstChild); } else { xml.DocumentElement.AppendChild(commentXmlNode); } await _io.Checkout(baseConfigFullPath); xml.Save(baseConfigFullPath); }
private async Task <EnvDTE.Project> InjectPowerShellScriptSupport() { _logger.LogInfo("Injecting PowerShell rich execution support to project"); if (!Project.Saved || !Project.DTE.Solution.Saved || string.IsNullOrEmpty(Project.FullName) || string.IsNullOrEmpty(Project.DTE.Solution.FullName)) { var saveDialogResult = MessageBox.Show(_ownerWindow, "Save pending changes to solution?", "Save pending changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (saveDialogResult == DialogResult.OK || saveDialogResult == DialogResult.Yes) { _dte.SaveAll(); } } if (!Project.Saved || !Project.DTE.Solution.Saved || string.IsNullOrEmpty(Project.FullName) || string.IsNullOrEmpty(Project.DTE.Solution.FullName)) { var saveDialogResult = MessageBox.Show(_ownerWindow, "Pending changes need to be saved. Please save the project and solution before adding PowerShell build scripts, then retry.", "Aborted", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk); if (saveDialogResult != DialogResult.Cancel) { _dte.SaveAll(); } _logger.LogInfo("Project or solution is not saved. Aborting."); return(null); } var projRoot = Project.GetProjectRoot(); if (projRoot.UsingTasks.Any(ut => ut.TaskName == "InvokePowerShell")) { return(Project); } var inlineTaskVersionDep_group = projRoot.AddPropertyGroup(); var inlineTaskVersionDep_v12 = inlineTaskVersionDep_group.AddProperty("InlineTaskVersionDep", "v$(MSBuildToolsVersion)"); inlineTaskVersionDep_v12.Condition = "'$(MSBuildToolsVersion)' == '12'"; var inlineTaskVersionDep_v14 = inlineTaskVersionDep_group.AddProperty("InlineTaskVersionDep", "Core"); inlineTaskVersionDep_v14.Condition = "'$(MSBuildToolsVersion)' == '14'"; var usingTask = projRoot.AddUsingTask("InvokePowerShell", @"$(MSBuildToolsPath)\Microsoft.Build.Tasks.$(InlineTaskVersionDep).dll", null); usingTask.TaskFactory = "CodeTaskFactory"; var utParameters = usingTask.AddParameterGroup(); var utParamsScriptFile = utParameters.AddParameter("ScriptFile"); utParamsScriptFile.ParameterType = "System.String"; utParamsScriptFile.Required = "true"; if (!projRoot.PropertyGroups.Any(pg => pg.Label == "InvokeBeforeAfter")) { var invokeBeforeAfterGroup = projRoot.AddItemGroup(); invokeBeforeAfterGroup.Label = "InvokeBeforeAfter"; var invokeBefore = invokeBeforeAfterGroup.AddItem("AvailableItemName", "InvokeBefore"); invokeBefore.AddMetadata("Visible", "false"); var invokeAfter = invokeBeforeAfterGroup.AddItem("AvailableItemName", "InvokeAfter"); invokeAfter.AddMetadata("Visible", "false"); } var psScriptsBefore = projRoot.AddTarget("PSScriptsBefore"); psScriptsBefore.BeforeTargets = "Build"; var invokeBeforeExec = psScriptsBefore.AddTask("InvokePowerShell"); invokeBeforeExec.SetParameter("ScriptFile", "%(InvokeBefore.Identity)"); invokeBeforeExec.Condition = "'@(InvokeBefore)' != ''"; var psScriptsAfter = projRoot.AddTarget("PSScriptsAfter"); psScriptsAfter.AfterTargets = "Build"; var invokeAfterExec = psScriptsAfter.AddTask("InvokePowerShell"); invokeAfterExec.SetParameter("ScriptFile", "%(InvokeAfter.Identity)"); invokeAfterExec.Condition = "'@(InvokeAfter)' != ''"; _projectProperties.PowerShellBuildEnabled = true; var projectRootPath = Project.FullName; Project = await Project.SaveProjectRoot(); VsEnvironment.Dte.UnloadProject(Project); var projXml = File.ReadAllText(projectRootPath); // ReSharper disable StringIndexOfIsCultureSpecific.1 // ReSharper disable StringIndexOfIsCultureSpecific.2 var injectLocation = projXml.IndexOf("</UsingTask", projXml.IndexOf("<UsingTask TaskName=\"InvokePowerShell\"")); projXml = projXml.Substring(0, injectLocation) + @" <Task> <Reference Include=""Microsoft.Build"" /> <Reference Include=""System.Management.Automation"" /> <Reference Include=""System.Xml"" /> <Using Namespace=""System.Management.Automation"" /> <Using Namespace=""System.Management.Automation.Runspaces"" /> <Using Namespace=""Microsoft.Build.Evaluation"" /> <Code Type=""Fragment"" Language=""cs""><![CDATA[ if (!ScriptFile.ToLower().EndsWith("".ps1"")) return true; var envdir = Environment.CurrentDirectory; BuildEngine.LogMessageEvent(new BuildMessageEventArgs(""Executing with PowerShell: "" + ScriptFile, """", """", MessageImportance.High)); Project project = ProjectCollection.GlobalProjectCollection.GetLoadedProjects(BuildEngine.ProjectFileOfTaskNode).FirstOrDefault() ?? new Project(BuildEngine.ProjectFileOfTaskNode); if (!ScriptFile.Contains("":"") && !ScriptFile.StartsWith(""\\\\"")) ScriptFile = project.DirectoryPath + ""\\"" + ScriptFile; var pwd = Directory.GetParent(ScriptFile).FullName; var runspaceConfig = RunspaceConfiguration.Create(); using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig)) { runspace.Open(); var vars = new System.Text.StringBuilder(); foreach (ProjectProperty evaluatedProperty in project.AllEvaluatedProperties) { var name = evaluatedProperty.Name; var value = evaluatedProperty.EvaluatedValue; if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(value)) { if (value.ToLower() == ""true"" || value.ToLower() == ""false"") { vars.AppendLine(""$"" + name + "" = $"" + value); } else { vars.AppendLine(""$"" + name + "" = @\""\r\n"" + value.Replace(""\"""", ""\""\"""") + ""\r\n\""@""); } } } using (RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace)) { using (Pipeline pipeline = runspace.CreatePipeline()) { scriptInvoker.Invoke(vars.ToString()); scriptInvoker.Invoke(""cd \"""" + pwd + ""\""""); var fileName = ScriptFile.Substring(project.DirectoryPath.Length + 1); pipeline.Commands.AddScript(""& \"""" + ScriptFile + ""\""""); try { var results = pipeline.Invoke(); var sbout = new StringBuilder(); foreach (var result in results) { sbout.AppendLine(result.ToString()); } BuildEngine.LogMessageEvent(new BuildMessageEventArgs(sbout.ToString(), """", """", MessageImportance.High)); } catch (Exception e) { BuildEngine.LogErrorEvent(new BuildErrorEventArgs("""", """", ScriptFile, 0, 0, 0, 0, e.ToString(), """", """", DateTime.Now)); throw; } } } } Environment.CurrentDirectory = envdir; return true; ]]></Code> </Task>" + projXml.Substring(injectLocation); if (await _io.ItemIsUnderSourceControl(projectRootPath)) { await _io.Checkout(projectRootPath); } File.WriteAllText(projectRootPath, projXml); _logger.LogInfo("Project file is now updated."); VsEnvironment.Dte.ReloadJustUnloadedProject(); return(VsEnvironment.Dte.GetProjectByFullName(projectRootPath)); }
private async Task <EnvDTE.Project> InjectNodeJSScriptSupport() { _logger.LogInfo("Injecting NodeJS rich execution support to project"); if (!Project.Saved || !Project.DTE.Solution.Saved || string.IsNullOrEmpty(Project.FullName) || string.IsNullOrEmpty(Project.DTE.Solution.FullName)) { var saveDialogResult = MessageBox.Show(_ownerWindow, "Save pending changes to solution?", "Save pending changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (saveDialogResult == DialogResult.OK || saveDialogResult == DialogResult.Yes) { _dte.SaveAll(); } } if (!Project.Saved || !Project.DTE.Solution.Saved || string.IsNullOrEmpty(Project.FullName) || string.IsNullOrEmpty(Project.DTE.Solution.FullName)) { var saveDialogResult = MessageBox.Show(_ownerWindow, "Pending changes need to be saved. Please save the project and solution before adding NodeJS build scripts, then retry.", "Aborted", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk); if (saveDialogResult != DialogResult.Cancel) { _dte.SaveAll(); } _logger.LogInfo("Project or solution is not saved. Aborting."); return(null); } var projRoot = Project.GetProjectRoot(); if (projRoot.UsingTasks.Any(ut => ut.TaskName == "InvokeNodeJS")) { return(Project); } var inlineTaskVersionDep_group = projRoot.AddPropertyGroup(); var inlineTaskVersionDep_v12 = inlineTaskVersionDep_group.AddProperty("InlineTaskVersionDep", "v$(MSBuildToolsVersion)"); inlineTaskVersionDep_v12.Condition = "'$(MSBuildToolsVersion)' == '12'"; var inlineTaskVersionDep_v14 = inlineTaskVersionDep_group.AddProperty("InlineTaskVersionDep", "Core"); inlineTaskVersionDep_v14.Condition = "'$(MSBuildToolsVersion)' == '14'"; var usingTask = projRoot.AddUsingTask("InvokeNodeJS", @"$(MSBuildToolsPath)\Microsoft.Build.Tasks.$(InlineTaskVersionDep).dll", null); usingTask.TaskFactory = "CodeTaskFactory"; var utParameters = usingTask.AddParameterGroup(); var utParamsScriptFile = utParameters.AddParameter("ScriptFile"); utParamsScriptFile.ParameterType = "System.String"; utParamsScriptFile.Required = "true"; if (!projRoot.PropertyGroups.Any(pg => pg.Label == "InvokeBeforeAfter")) { var invokeBeforeAfterGroup = projRoot.AddItemGroup(); invokeBeforeAfterGroup.Label = "InvokeBeforeAfter"; var invokeBefore = invokeBeforeAfterGroup.AddItem("AvailableItemName", "InvokeBefore"); invokeBefore.AddMetadata("Visible", "false"); var invokeAfter = invokeBeforeAfterGroup.AddItem("AvailableItemName", "InvokeAfter"); invokeAfter.AddMetadata("Visible", "false"); } var psScriptsBefore = projRoot.AddTarget("NodeJSScriptsBefore"); psScriptsBefore.BeforeTargets = "Build"; var invokeBeforeExec = psScriptsBefore.AddTask("InvokeNodeJS"); invokeBeforeExec.SetParameter("ScriptFile", "%(InvokeBefore.Identity)"); invokeBeforeExec.Condition = "'@(InvokeBefore)' != ''"; var psScriptsAfter = projRoot.AddTarget("NodeJSScriptsAfter"); psScriptsAfter.AfterTargets = "Build"; var invokeAfterExec = psScriptsAfter.AddTask("InvokeNodeJS"); invokeAfterExec.SetParameter("ScriptFile", "%(InvokeAfter.Identity)"); invokeAfterExec.Condition = "'@(InvokeAfter)' != ''"; _projectProperties.NodeJSBuildEnabled = true; var projectRootPath = Project.FullName; Project = await Project.SaveProjectRoot(); VsEnvironment.Dte.UnloadProject(Project); var projXml = File.ReadAllText(projectRootPath); // ReSharper disable StringIndexOfIsCultureSpecific.1 // ReSharper disable StringIndexOfIsCultureSpecific.2 var injectLocation = projXml.IndexOf("</UsingTask", projXml.IndexOf("<UsingTask TaskName=\"InvokeNodeJS\"")); projXml = projXml.Substring(0, injectLocation) + @" <Task> <Reference Include=""Microsoft.Build"" /> <Reference Include=""System.Xml"" /> <Using Namespace=""Microsoft.Build.Evaluation"" /> <Using Namespace=""System.Text"" /> <Using Namespace=""System.Text.RegularExpressions"" /> <Using Namespace=""System.Threading"" /> <Using Namespace=""System.IO"" /> <Using Namespace=""System.Diagnostics"" /> <Code Type=""Fragment"" Language=""cs""><![CDATA[ if (!ScriptFile.ToLower().EndsWith("".js"")) return true; var envdir = Environment.CurrentDirectory; var runSuccess = true; BuildEngine.LogMessageEvent(new BuildMessageEventArgs(""Executing as NodeJS REPL: "" + ScriptFile, """", """", MessageImportance.High)); Project project = ProjectCollection.GlobalProjectCollection.GetLoadedProjects(BuildEngine.ProjectFileOfTaskNode).FirstOrDefault() ?? new Project(BuildEngine.ProjectFileOfTaskNode); if (!ScriptFile.Contains("":"") && !ScriptFile.StartsWith(""\\\\"")) ScriptFile = project.DirectoryPath + ""\\"" + ScriptFile; var pwd = Directory.GetParent(ScriptFile).FullName; var vars = new System.Text.StringBuilder(); vars.AppendLine(""var msbuild = { properties: {} };""); foreach (ProjectProperty evaluatedProperty in project.AllEvaluatedProperties) { var name = evaluatedProperty.Name; var value = evaluatedProperty.EvaluatedValue; if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(value)) { if (value.ToLower() == ""true"" || value.ToLower() == ""false"") { vars.AppendLine(""msbuild.properties[\"""" + name + ""\""] = "" + value + "";""); } else { vars.AppendLine(""msbuild.properties[\"""" + name + ""\""] = \"""" + value.Replace(""\\"", ""\\\\"") .Replace(""\"""", ""\\\"""") .Replace(""\r"", """") .Replace(""\n"", ""\\n"") + ""\"";""); } } } var process = new Process { StartInfo = new ProcessStartInfo { FileName = ""node.exe"", UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, Arguments = ""-i"", WorkingDirectory = pwd } }; var loadingScript = false; process.OutputDataReceived += (sender, args) => { if (!string.IsNullOrWhiteSpace(args.Data) && args.Data != ""> "" && args.Data != ""undefined"" && loadingScript) { var data = args.Data.Replace(""\r"","""").Replace(""\n"", ""\r\n""); while (data.StartsWith(""> "") || Regex.IsMatch(data, @""\.+ "")) { if (data.StartsWith(""> "")) data = data.Substring(2); if (Regex.IsMatch(data, @""\.+ "")) data = data.Substring(Regex.Match(data, @""\.+ "").ToString().Length); } if (data == ""undefined"") return; if (Regex.IsMatch(data, ""\\w*Error: "")) { BuildEngine.LogErrorEvent(new BuildErrorEventArgs("""", """", ScriptFile, 0, 0, 0, 0, data, """", """", DateTime.Now)); process.EnableRaisingEvents = false; // block stack trace; sorry, no support for JS stack trace when using REPL runSuccess = false; } else { if (runSuccess) { // block stack trace; sorry, no support for JS stack trace when using REPL BuildEngine.LogMessageEvent(new BuildMessageEventArgs(data, """", """", MessageImportance.High)); } } } }; process.ErrorDataReceived += (sender, args) => { var data = args.Data; if (string.IsNullOrWhiteSpace(data)) return; BuildEngine.LogErrorEvent(new BuildErrorEventArgs("""", """", ScriptFile, 0, 0, 0, 0, data, """", """", DateTime.Now)); runSuccess = false; }; process.Start(); process.EnableRaisingEvents = true; process.BeginOutputReadLine(); process.StandardInput.WriteLine(vars.ToString()); Thread.Sleep(250); loadingScript = true; process.StandardInput.WriteLine("".load "" + ScriptFile.Replace(""\\"", ""\\\\"")); process.StandardInput.WriteLine(""process.exit()""); process.WaitForExit(); Environment.CurrentDirectory = envdir; return runSuccess; ]]></Code> </Task>" + projXml.Substring(injectLocation); if (await _io.ItemIsUnderSourceControl(projectRootPath)) { await _io.Checkout(projectRootPath); } File.WriteAllText(projectRootPath, projXml); _logger.LogInfo("Project file is now updated."); VsEnvironment.Dte.ReloadJustUnloadedProject(); Project = VsEnvironment.Dte.GetProjectByFullName(projectRootPath); return(Project); }