/// <summary> /// This is used to report progress during the build process and possibly update the current step /// </summary> /// <param name="step">The current build step</param> /// <param name="message">The message to report</param> /// <param name="args">A list of arguments to format into the message text</param> protected void ReportProgress(BuildStep step, string message, params object[] args) { BuildProgressEventArgs pa; TimeSpan runtime; if(this.CancellationToken != CancellationToken.None && !buildCancelling) this.CancellationToken.ThrowIfCancellationRequested(); bool stepChanged = (this.CurrentBuildStep != step); if(stepChanged) { // Don't bother reporting elapsed time for the initialization steps if(step > BuildStep.GenerateSharedContent) { runtime = DateTime.Now - stepStart; pa = new BuildProgressEventArgs(this.CurrentBuildStep, false, String.Format(CultureInfo.CurrentCulture, " Last step completed in " + "{0:00}:{1:00}:{2:00.0000}", Math.Floor(runtime.TotalSeconds / 3600), Math.Floor((runtime.TotalSeconds % 3600) / 60), (runtime.TotalSeconds % 60))); if(swLog != null) swLog.WriteLine(pa.Message); if(this.ProgressReportProvider != null) this.ProgressReportProvider.Report(pa); } if(this.ProgressReportProvider != null) this.ProgressReportProvider.Report(new BuildProgressEventArgs(this.CurrentBuildStep, false, "-------------------------------")); stepStart = DateTime.Now; this.CurrentBuildStep = step; if(swLog != null) swLog.WriteLine("</buildStep>\r\n<buildStep step=\"{0}\">", step); } pa = new BuildProgressEventArgs(this.CurrentBuildStep, stepChanged, String.Format(CultureInfo.CurrentCulture, message, args)); // Save the message to the log file if(swLog != null) swLog.WriteLine(HttpUtility.HtmlEncode(pa.Message)); if(this.ProgressReportProvider != null) this.ProgressReportProvider.Report(pa); }
/// <summary> /// This raises the <see cref="BuildProgress"/> event. /// </summary> /// <param name="e">The event arguments</param> protected virtual void OnBuildProgress(BuildProgressEventArgs e) { var handler = BuildProgress; if(handler != null) handler(this, e); }
//===================================================================== /// <summary> /// Constructor /// </summary> /// <param name="buildProject">The project to build</param> /// <overloads>There are two overloads for the constructor.</overloads> public BuildProcess(SandcastleProject buildProject) { project = buildProject; // Save a copy of the project filename. If using a temporary project, it won't match the passed // project's name. originalProjectName = buildProject.Filename; apiTocOrder = -1; apiTocParentId = rootContentContainerId = String.Empty; progressArgs = new BuildProgressEventArgs(); fieldMatchEval = new MatchEvaluator(OnFieldMatch); contentMatchEval = new MatchEvaluator(OnContentMatch); linkMatchEval = new MatchEvaluator(OnLinkMatch); codeBlockMatchEval = new MatchEvaluator(OnCodeBlockMatch); excludeElementEval = new MatchEvaluator(OnExcludeElement); help1Files = new Collection<string>(); help2Files = new Collection<string>(); helpViewerFiles = new Collection<string>(); websiteFiles = new Collection<string>(); openXmlFiles = new Collection<string>(); helpFormatOutputFolders = new Collection<string>(); }
//===================================================================== /// <summary> /// This is called by the build process thread to update the main /// window with the current build step. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down or it hasn't // completed yet. if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>( buildProcess_BuildStepChanged), new object[] { sender, e }); } else { lblProgress.Text = e.BuildStep.ToString(); if(e.HasCompleted) { reflectionFile = buildProcess.ReflectionInfoFilename; // Restore the current project's base path Directory.SetCurrentDirectory(Path.GetDirectoryName( apiFilter.Project.Filename)); // If successful, load the namespace nodes, and enable // the UI. if(e.BuildStep == BuildStep.Completed) { // Convert the build API filter to a dictionary to make // it easier to find entries. buildFilterEntries = new Dictionary<string, ApiFilter>(); this.ConvertApiFilter(buildProcess.BuildApiFilter); this.LoadNamespaces(); tvApiList.Enabled = splitContainer.Panel2.Enabled = btnReset.Enabled = true; } pbWait.Visible = lblLoading.Visible = false; buildThread = null; buildProcess = null; } } }
//===================================================================== /// <summary> /// Constructor /// </summary> /// <param name="buildProject">The project to build</param> /// <overloads>There are two overloads for the constructor.</overloads> public BuildProcess(SandcastleProject buildProject) { // If the project isn't using final values suitable for the build, // create a new project that is using final values. if(buildProject.UsingFinalValues) project = buildProject; else project = new SandcastleProject(buildProject, true); // Save a copy of the project filename. If using a temporary // project, it won't match the passed project's name. originalProjectName = buildProject.Filename; apiTocOrder = -1; apiTocParentId = rootContentContainerId = String.Empty; progressArgs = new BuildProgressEventArgs(); fieldMatchEval = new MatchEvaluator(OnFieldMatch); contentMatchEval = new MatchEvaluator(OnContentMatch); linkMatchEval = new MatchEvaluator(OnLinkMatch); codeBlockMatchEval = new MatchEvaluator(OnCodeBlockMatch); excludeElementEval = new MatchEvaluator(OnExcludeElement); help1Files = new Collection<string>(); help2Files = new Collection<string>(); helpViewerFiles = new Collection<string>(); websiteFiles = new Collection<string>(); helpFormatOutputFolders = new Collection<string>(); }
//===================================================================== // Build methods /// <summary> /// This is called by the build process thread to update the main /// window with the current build step. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down or it hasn't // completed yet. if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>( buildProcess_BuildStepChanged), new object[] { sender, e }); } else { lblProgress.Text = e.BuildStep.ToString(); if(e.HasCompleted) { // Switch back to the current project's folder Directory.SetCurrentDirectory(Path.GetDirectoryName( nsColl.Project.Filename)); // If successful, load the namespace nodes, and enable // the UI. if(e.BuildStep == BuildStep.Completed) { this.LoadNamespaces(buildProcess.ReflectionInfoFilename); cboAssembly.Enabled = txtSearchText.Enabled = btnApplyFilter.Enabled = btnAll.Enabled = btnNone.Enabled = true; } pbWait.Visible = lblProgress.Visible = false; lbNamespaces.Focus(); buildThread = null; buildProcess = null; } } }
/// <summary> /// This is called by the build process thread to update the main /// window with information about its progress. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>( buildProcess_BuildProgress), new object[] { sender, e }); } else { if(e.BuildStep == BuildStep.Failed) { MessageBox.Show("Unable to build project to obtain " + "API information. Please perform a normal build " + "to identify and correct the problem.", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// This is called by the build process thread to update the application with the current build step /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { builder.ReportProgress(e.BuildStep.ToString()); lastBuildStep = e.BuildStep; }
/// <summary> /// This is called by the build process thread to update the main window with the current build step /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down or it hasn't // completed yet. if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>(buildProcess_BuildStepChanged), new object[] { sender, e }); } else { if(!Settings.Default.VerboseLogging) outputWindow.AppendText(e.BuildStep.ToString()); if(e.HasCompleted) { StatusBarTextProvider.ResetProgressBar(); this.SetUIEnabledState(true); outputWindow.LogFile = buildProcess.LogFilename; buildThread = null; buildProcess = null; if(e.BuildStep == BuildStep.Completed && Settings.Default.OpenHelpAfterBuild) miViewHelpFile.PerformClick(); } } }
/// <summary> /// This is called by the build process thread to update the application with the current build step /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { string outputPath; if(!this.Verbose) Log.LogMessage(MessageImportance.High, e.BuildStep.ToString()); if(e.HasCompleted) { // If successful, report the location of the help file/website if(e.BuildStep == BuildStep.Completed) { outputPath = buildProcess.OutputFolder + buildProcess.ResolvedHtmlHelpName; switch(sandcastleProject.HelpFileFormat) { case HelpFileFormats.HtmlHelp1: outputPath += ".chm"; break; case HelpFileFormats.MSHelp2: outputPath += ".hxs"; break; case HelpFileFormats.MSHelpViewer: outputPath += ".mshc"; break; case HelpFileFormats.OpenXml: outputPath += ".docx"; break; default: break; } // Report single file or multi-format output location if(File.Exists(outputPath)) Log.LogMessage(MessageImportance.High, "The help file is located at: {0}", outputPath); else Log.LogMessage(MessageImportance.High, "The help output is located at: {0}", buildProcess.OutputFolder); } if(File.Exists(buildProcess.LogFilename)) Log.LogMessage(MessageImportance.High, "Build details can be found in {0}", buildProcess.LogFilename); } lastBuildStep = e.BuildStep; }
/// <summary> /// This is called by the build process thread to update the task with information about progress /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { Match m = reParseMessage.Match(e.Message); // Always log errors and warnings if(m.Success) { if(String.Compare(m.Groups[3].Value, "warning", StringComparison.OrdinalIgnoreCase) == 0) Log.LogWarning(null, m.Groups[4].Value, m.Groups[4].Value, m.Groups[1].Value, 0, 0, 0, 0, m.Groups[5].Value.Trim()); else if(String.Compare(m.Groups[3].Value, "error", StringComparison.OrdinalIgnoreCase) == 0) Log.LogError(null, m.Groups[4].Value, m.Groups[4].Value, m.Groups[1].Value, 0, 0, 0, 0, m.Groups[5].Value.Trim()); else Log.LogMessage(MessageImportance.High, e.Message); } else if(this.Verbose) Log.LogMessage(MessageImportance.High, e.Message); else { // If not doing verbose logging, show warnings and let MSBuild filter them out if not // wanted. Errors will kill the build so we don't have to deal with them here. if(reWarning.IsMatch(e.Message)) Log.LogWarning(e.Message); } }
/// <summary> /// This is called by the build process thread to update the main /// window with information about its progress. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { try { // Ignore it if we've already shut down if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>(buildProcess_BuildProgress), new object[] { sender, e }); } catch(Exception) { // Ignore these as we still get one occasionally due to the object being // disposed even though we do check for it first. } } else { if(e.BuildStep == BuildStep.Failed) { MessageBox.Show("Unable to build project to obtain " + "API information. Please perform a normal build " + "to identify and correct the problem.", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// This is called by the build process thread to update the /// task with information about progress. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { Match m = reParseMessage.Match(e.Message); // Always log errors and warnings if(m.Success) { if(String.Compare(m.Groups[3].Value, "warning", StringComparison.OrdinalIgnoreCase) == 0) Log.LogWarning(null, m.Groups[4].Value, m.Groups[4].Value, m.Groups[1].Value, 0, 0, 0, 0, m.Groups[5].Value.Trim()); else if(String.Compare(m.Groups[3].Value, "error", StringComparison.OrdinalIgnoreCase) == 0) Log.LogError(null, m.Groups[4].Value, m.Groups[4].Value, m.Groups[1].Value, 0, 0, 0, 0, m.Groups[5].Value.Trim()); else Log.LogMessage(e.Message); } else if(verbose) Log.LogMessage(e.Message); }
/// <summary> /// This is called by the build process thread to update the main /// window with the current build step. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildStepChanged(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down or it hasn't // completed yet. if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>(buildProcess_BuildStepChanged), new object[] { sender, e }); } else { lblLoading.Text = e.BuildStep.ToString(); if(e.HasCompleted) { // Restore the current project's base path Directory.SetCurrentDirectory(Path.GetDirectoryName(currentProject.Filename)); lastBuildStep = e.BuildStep; } } }
//===================================================================== /// <summary> /// This is used to report build progress /// </summary> /// <param name="e">The event arguments</param> private void buildProcess_ReportProgress(BuildProgressEventArgs e) { if(!this.IsDisposed) { if(e.BuildStep < BuildStep.Completed) StatusBarTextProvider.UpdateProgress((int)e.BuildStep); if(Settings.Default.VerboseLogging || e.BuildStep == BuildStep.Failed) outputWindow.AppendText(e.Message); else { if(e.StepChanged) outputWindow.AppendText(e.BuildStep.ToString()); // If not doing verbose logging, show warnings. Errors will kill the build so we don't have to // deal with them here. if(reWarning.IsMatch(e.Message)) outputWindow.AppendText(e.Message); } } }
/// <summary> /// This is called by the build process thread to update the main window with information about its /// progress. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>(buildProcess_BuildProgress), new object[] { sender, e }); } else { if(e.BuildStep < BuildStep.Completed) StatusBarTextProvider.UpdateProgress((int)e.BuildStep); if(Settings.Default.VerboseLogging || e.BuildStep == BuildStep.Failed) outputWindow.AppendText(e.Message); else { // If not doing verbose logging, show warnings and let MSBuild filter them out if not // wanted. Errors will kill the build so we don't have to deal with them here. if(reWarning.IsMatch(e.Message)) outputWindow.AppendText(e.Message); } } }
//===================================================================== /// <summary> /// This is used to report build progress /// </summary> /// <param name="e">The event arguments</param> private void buildProcess_ReportProgress(BuildProgressEventArgs e) { if(e.StepChanged) lblProgress.Text = e.BuildStep.ToString(); }
/// <summary> /// This is called by the build process thread to update the main /// window with information about its progress. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void buildProcess_BuildProgress(object sender, BuildProgressEventArgs e) { if(this.InvokeRequired) { // Ignore it if we've already shut down if(!this.IsDisposed) this.Invoke(new EventHandler<BuildProgressEventArgs>( buildProcess_BuildProgress), new object[] { sender, e }); } else { if(e.BuildStep < BuildStep.Completed) StatusBarTextProvider.UpdateProgress((int)e.BuildStep); if(Settings.Default.VerboseLogging || e.BuildStep == BuildStep.Failed) outputWindow.AppendText(e.Message); } }