/// <summary> /// This method is used to execute the plug-in during the build process /// </summary> /// <param name="context">The current execution context</param> public void Execute(Utils.PlugIn.ExecutionContext context) { SandcastleProject project; string workingPath; bool success; // Update shared content version items if (context.BuildStep == BuildStep.GenerateSharedContent) { this.UpdateVersionItems(); return; } // Set the current version's reflection info filename and sort the // collection so that the versions are in ascending order. currentVersion.ReflectionFilename = builder.ReflectionInfoFilename; allVersions.Sort(); // Merge the version information builder.ReportProgress("\r\nPerforming partial builds on prior version projects"); // Build each of the projects foreach (VersionSettings vs in allVersions) { // Not needed for current project if (vs.HelpFileProject == null) { continue; } project = new SandcastleProject(vs.HelpFileProject, true); // We'll use a working folder below the current project's working folder workingPath = builder.WorkingFolder + vs.HelpFileProject.GetHashCode().ToString("X", CultureInfo.InvariantCulture) + "\\"; success = this.BuildProject(project, workingPath); // Switch back to the original folder for the current project Directory.SetCurrentDirectory(builder.ProjectFolder); if (!success) { throw new BuilderException("VBP0004", "Unable to build prior version project: " + project.Filename); } // Save the reflection file location as we need it later vs.ReflectionFilename = workingPath + "reflection.org"; } // Create the Version Builder configuration and script file // and run it. builder.ReportProgress("\r\nCreating and running Version Builder script"); builder.RunProcess(this.CreateVersionBuilderScript(), null); builder.ReportProgress("\r\nVersion information merged\r\n"); }
/// <summary> /// This method is used to execute the plug-in during the build process /// </summary> /// <param name="context">The current execution context</param> public void Execute(Utils.PlugIn.ExecutionContext context) { XmlNamespaceManager nsm; XmlDocument project; XmlNode property; string projectFile; // Localize the content when extracting keyword and TOC info if (context.BuildStep == BuildStep.ExtractingHtmlInfo) { builder.ReportProgress("Adding DBCS Fix localization folder"); projectFile = builder.WorkingFolder + "ExtractHtmlInfo.proj"; project = new XmlDocument(); project.Load(projectFile); nsm = new XmlNamespaceManager(project.NameTable); nsm.AddNamespace("MSBuild", project.DocumentElement.NamespaceURI); property = project.SelectSingleNode("//MSBuild:LocalizedFolder", nsm); if (property == null) { throw new BuilderException("DFP0004", "Unable to locate " + "LocalizedFolder element in project file"); } property.InnerText = @".\Localized"; project.Save(projectFile); return; } if (builder.CurrentFormat != HelpFileFormat.HtmlHelp1) { return; } builder.ReportProgress("Adding localization options to build task"); projectFile = builder.WorkingFolder + "Build1xHelpFile.proj"; project = new XmlDocument(); project.Load(projectFile); nsm = new XmlNamespaceManager(project.NameTable); nsm.AddNamespace("MSBuild", project.DocumentElement.NamespaceURI); property = project.SelectSingleNode("//MSBuild:WorkingFolder", nsm); if (property == null) { throw new BuilderException("DFP0005", "Unable to locate " + "WorkingFolder element in project file"); } property.InnerText = @".\Localized"; property = project.SelectSingleNode("//MSBuild:LocalizeApp", nsm); if (property == null) { throw new BuilderException("DFP0006", "Unable to locate " + "LocalizeApp element in project file"); } property.InnerText = sbAppLocalePath; project.Save(projectFile); }
/// <summary> /// This method is used to execute the plug-in during the build process /// </summary> /// <param name="context">The current execution context</param> public void Execute(Utils.PlugIn.ExecutionContext context) { XmlNamespaceManager nsm; XmlDocument project; XmlNode target, task; XmlAttribute attr; string projectFile; projectFile = builder.WorkingFolder + "GenerateRefInfo.proj"; // If the project doesn't exist we have nothing to do. However, it // could be that some other plug-in has bypassed it so only issue // a warning. if (!File.Exists(projectFile)) { builder.ReportWarning("SSP0002", "The reflection information " + "generation project '{0}' could not be found. The " + "Script# plug-in did not run.", projectFile); return; } builder.ReportProgress("Adding Script# AfterGenerateRefInfo tasks"); // Add the transform that fixes up the Script# elements to // the AfterGenerateRefInfo project target. Note that we use a // customized version that adds a <scriptSharp /> element to each // API node so that our custom JavaScript syntax generator applies // the casing rules to the member names. project = new XmlDocument(); project.Load(projectFile); nsm = new XmlNamespaceManager(project.NameTable); nsm.AddNamespace("MSBuild", project.DocumentElement.NamespaceURI); target = project.SelectSingleNode( "//MSBuild:Target[@Name='AfterGenerateRefInfo']", nsm); if (target == null) { throw new BuilderException("SSP0001", "Unable to locate " + "AfterGenerateRefInfo target in project file"); } task = project.CreateElement("Message", nsm.LookupNamespace("MSBuild")); attr = project.CreateAttribute("Text"); attr.Value = "Fixing up Script# elements..."; task.Attributes.Append(attr); target.AppendChild(task); task = project.CreateElement("Copy", nsm.LookupNamespace("MSBuild")); attr = project.CreateAttribute("SourceFiles"); attr.Value = "reflection.org"; task.Attributes.Append(attr); attr = project.CreateAttribute("DestinationFiles"); attr.Value = "scriptsharp.org"; task.Attributes.Append(attr); target.AppendChild(task); task = project.CreateElement("XslTransform", nsm.LookupNamespace("MSBuild")); attr = project.CreateAttribute("SandcastlePath"); attr.Value = "$(SandcastlePath)"; task.Attributes.Append(attr); attr = project.CreateAttribute("WorkingFolder"); attr.Value = "$(WorkingFolder)"; task.Attributes.Append(attr); attr = project.CreateAttribute("Transformations"); attr.Value = Path.Combine(builder.TemplateFolder, "FixScriptSharp.xsl"); task.Attributes.Append(attr); attr = project.CreateAttribute("InputFile"); attr.Value = "scriptsharp.org"; task.Attributes.Append(attr); attr = project.CreateAttribute("OutputFile"); attr.Value = "reflection.org"; task.Attributes.Append(attr); target.AppendChild(task); project.Save(projectFile); }
/// <summary> /// This method is used to execute the plug-in during the build process /// </summary> /// <param name="context">The current execution context</param> public void Execute(Utils.PlugIn.ExecutionContext context) { SandcastleProject project; StringBuilder sb = new StringBuilder(1024); string workingPath, configFilename; bool success; if (context.BuildStep == BuildStep.ApplyVisibilityProperties) { // Merge the additional reference links information builder.ReportProgress("Performing partial builds on additional targets' projects"); // Build each of the projects foreach (ReferenceLinkSettings vs in otherLinks) { project = new SandcastleProject(vs.HelpFileProject, true); // We'll use a working folder below the current project's // working folder. workingPath = builder.WorkingFolder + vs.HelpFileProject.GetHashCode().ToString("X", CultureInfo.InvariantCulture) + "\\"; success = this.BuildProject(project, workingPath); // Switch back to the original folder for the current // project. Directory.SetCurrentDirectory(builder.ProjectFolder); if (!success) { throw new BuilderException("ARL0003", "Unable to build " + "additional target project: " + project.Filename); } // Save the reflection file location as we need it later vs.ReflectionFilename = workingPath + "reflection.xml"; sb.AppendFormat("\"{0}ProductionTools\\XslTransform\" " + "/xsl:\"{0}ProductionTransforms\\ApplyVSDocModel.xsl\"," + "\"{0}ProductionTransforms\\AddGuidFilenames.xsl\" " + "\"{1}reflection.org\" /out:\"{1}reflection.xml\" " + "/arg:IncludeAllMembersTopic=true " + "/arg:IncludeInheritedOverloadTopics=true\r\n", builder.SandcastleFolder, workingPath); } // Run the Transform step on the reflection.org files. This // adds some stuff the build components need. sb.Insert(0, "@ECHO OFF\r\n"); workingPath = builder.WorkingFolder + "TransformReferences.bat"; using (StreamWriter sw = new StreamWriter(workingPath)) { sw.Write(sb.ToString()); } builder.ReportProgress("\r\nTransforming reference reflection files..."); builder.RunProcess(workingPath, null); return; } // Merge the reflection file info into conceptual.config configFilename = builder.WorkingFolder + "conceptual.config"; if (File.Exists(configFilename)) { this.MergeReflectionInfo(configFilename, true); } // Merge the reflection file info into sancastle.config configFilename = builder.WorkingFolder + "sandcastle.config"; if (File.Exists(configFilename)) { this.MergeReflectionInfo(configFilename, false); } }
/// <summary> /// This method is used to execute the plug-in during the build process /// </summary> /// <param name="context">The current execution context</param> public void Execute(Utils.PlugIn.ExecutionContext context) { Encoding enc = Encoding.Default; Thread browserThread; XmlDocument sharedContent; XPathNavigator navContent, item; XmlCommentsFile comments; string sharedContentFilename, workingPath, content; // Copy any XML comments files from the project to the working // folder. Solutions, projects, and assemblies are ignored as // they won't be used with this build type. if (context.BuildStep == BuildStep.ValidatingDocumentationSources) { builder.ExecuteBeforeStepPlugIns(); foreach (DocumentationSource ds in builder.CurrentProject.DocumentationSources) { foreach (string commentsName in DocumentationSource.CommentsFiles(ds.SourceFile, ds.IncludeSubFolders)) { workingPath = builder.WorkingFolder + Path.GetFileName(commentsName); // Warn if there is a duplicate and copy the comments // file to a unique name to preserve its content. if (File.Exists(workingPath)) { workingPath = builder.WorkingFolder + Guid.NewGuid().ToString("B"); builder.ReportWarning("BE0063", "'{0}' matches " + "a previously copied comments filename. The " + "duplicate will be copied to a unique name " + "to preserve the comments it contains.", commentsName); } File.Copy(commentsName, workingPath, true); File.SetAttributes(workingPath, FileAttributes.Normal); // Add the file to the XML comments file collection comments = new XmlCommentsFile(workingPath); // Fixup comments for CPP comments files? if (builder.CurrentProject.CppCommentsFixup) { comments.FixupComments(); } builder.CommentsFiles.Add(comments); builder.ReportProgress(" {0} -> {1}", commentsName, workingPath); } } builder.ExecuteAfterStepPlugIns(); return; } // Remove the version information items from the shared content // file as the AjaxDoc reflection file doesn't contain version // information. if (context.BuildStep == BuildStep.GenerateSharedContent) { builder.ReportProgress("Removing version information items " + "from shared content file"); sharedContentFilename = builder.WorkingFolder + "SharedBuilderContent.xml"; sharedContent = new XmlDocument(); sharedContent.Load(sharedContentFilename); navContent = sharedContent.CreateNavigator(); item = navContent.SelectSingleNode("content/item[@id='" + "locationInformation']"); if (item != null) { item.DeleteSelf(); } item = navContent.SelectSingleNode("content/item[@id='" + "assemblyNameAndModule']"); if (item != null) { item.DeleteSelf(); } sharedContent.Save(sharedContentFilename); return; } builder.ReportProgress("Using project '{0}'", projectName); if (regenerateFiles) { // Regenerate the files first. This is done by starting a // thread to invoke the AjaxDoc application via a web browser // control. This is necessary as the brower control needs to // run in a thread with a single-threaded apartment state. // We can't just request the page as AjaxDoc has to post back // to itself in order to store the generated information. builder.ReportProgress("Generating XML comments and " + "reflection information via AjaxDoc"); browserThread = new Thread(RunBrowser); browserThread.SetApartmentState(ApartmentState.STA); navCount = 0; browserThread.Start(); if (!browserThread.Join(11000)) { browserThread.Abort(); } if (!String.IsNullOrEmpty(errorText)) { throw new BuilderException("ADP0003", "AjaxDoc encountered " + "a scripting error: " + errorText); } if (commentsFile == null || reflectionFile == null) { throw new BuilderException("ADP0004", "Unable to produce " + "comments file and/or reflection file"); } builder.ReportProgress("Generated comments file '{0}' " + "and reflection file '{1}'", commentsFile, reflectionFile); } else { // Use the existing files commentsFile = "Output/" + projectName + ".xml"; reflectionFile = "Output/" + projectName + ".org"; builder.ReportProgress("Using existing XML comments file " + "'{0}' and reflection information file '{1}'", commentsFile, reflectionFile); } // Allow Before step plug-ins to run builder.ExecuteBeforeStepPlugIns(); // Download the files using (WebClient webClient = new WebClient()) { webClient.UseDefaultCredentials = userCreds.UseDefaultCredentials; if (!userCreds.UseDefaultCredentials) { webClient.Credentials = new NetworkCredential( userCreds.UserName, userCreds.Password); } webClient.CachePolicy = new RequestCachePolicy( RequestCacheLevel.NoCacheNoStore); if (proxyCreds.UseProxyServer) { webClient.Proxy = new WebProxy(proxyCreds.ProxyServer, true); if (!proxyCreds.Credentials.UseDefaultCredentials) { webClient.Proxy.Credentials = new NetworkCredential( proxyCreds.Credentials.UserName, proxyCreds.Credentials.Password); } } // Since there are only two, download them synchronously workingPath = builder.WorkingFolder + projectName + ".xml"; builder.ReportProgress("Downloading {0}", commentsFile); webClient.DownloadFile(ajaxDocUrl + commentsFile, workingPath); builder.CommentsFiles.Add(new XmlCommentsFile(workingPath)); builder.ReportProgress("Downloading {0}", reflectionFile); webClient.DownloadFile(ajaxDocUrl + reflectionFile, builder.ReflectionInfoFilename); builder.ReportProgress("Downloads completed successfully"); } // AjaxDoc 1.1 prefixes all member names with "J#" which causes // BuildAssembler's ResolveReferenceLinksComponent2 component in // the Sept 2007 CTP to crash. As such, we'll strip it out. I // can't see a need for it anyway. content = BuildProcess.ReadWithEncoding(workingPath, ref enc); content = content.Replace(":J#", ":"); using (StreamWriter sw = new StreamWriter(workingPath, false, enc)) { sw.Write(content); } content = BuildProcess.ReadWithEncoding( builder.ReflectionInfoFilename, ref enc); content = content.Replace(":J#", ":"); using (StreamWriter sw = new StreamWriter( builder.ReflectionInfoFilename, false, enc)) { sw.Write(content); } // Don't apply the filter in a partial build if (!builder.IsPartialBuild && builder.BuildApiFilter.Count != 0) { builder.ReportProgress("Applying API filter manually"); builder.ApplyManualApiFilter(builder.BuildApiFilter, builder.ReflectionInfoFilename); } // Allow After step plug-ins to run builder.ExecuteAfterStepPlugIns(); }