//=====================================================================

        /// <summary>
        /// This is used to start the background build process from which we will get the information to load the
        /// tree view.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private async void ApiFilterEditorDlg_Load(object sender, EventArgs e)
        {
            string tempPath;

            tvApiList.Enabled = splitContainer.Panel2.Enabled = btnReset.Enabled = false;

            try
            {
                // Clone the project for the build and adjust its properties for our needs
                tempProject = new SandcastleProject(apiFilter.Project.MSBuildProject);

                // Build output is stored in a temporary folder and it keeps the intermediate files
                tempProject.CleanIntermediates = false;
                tempPath = Path.GetTempFileName();

                File.Delete(tempPath);
                tempPath = Path.Combine(Path.GetDirectoryName(tempPath), "SHFBPartialBuild");

                if(!Directory.Exists(tempPath))
                    Directory.CreateDirectory(tempPath);

                tempProject.OutputPath = tempPath;

                cancellationTokenSource = new CancellationTokenSource();

                buildProcess = new BuildProcess(tempProject, PartialBuildType.GenerateReflectionInfo)
                {
                    ProgressReportProvider = new Progress<BuildProgressEventArgs>(buildProcess_ReportProgress),
                    CancellationToken = cancellationTokenSource.Token,
                    SuppressApiFilter = true        // We must suppress the current API filter for this build
                };

                await Task.Run(() => buildProcess.Build(), cancellationTokenSource.Token);

                if(!cancellationTokenSource.IsCancellationRequested)
                {
                    // 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(buildProcess.CurrentBuildStep == BuildStep.Completed)
                    {
                        reflectionFile = buildProcess.ReflectionInfoFilename;

                        // Convert the build API filter to a dictionary to make it easier to find entries
                        buildFilterEntries = new Dictionary<string, ApiFilter>();

                        this.ConvertApiFilter(buildProcess.CurrentProject.ApiFilter);
                        this.LoadNamespaces();

                        tvApiList.Enabled = splitContainer.Panel2.Enabled = btnReset.Enabled = true;
                    }
                    else
                        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);

                    pbWait.Visible = lblLoading.Visible = false;
                }
                else
                {
                    this.DialogResult = DialogResult.Cancel;
                    this.Close();
                }

                buildProcess = null;
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
                MessageBox.Show("Unable to build project to obtain API information.  Error: " +
                    ex.Message, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if(cancellationTokenSource != null)
                {
                    cancellationTokenSource.Dispose();
                    cancellationTokenSource = null;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Build the help file using the current project settings
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private async void miBuildProject_Click(object sender, EventArgs e)
        {
            if(project == null || !this.SaveBeforeBuild())
                return;

            miClearOutput_Click(miBuildProject, e);
            this.SetUIEnabledState(false);
            Application.DoEvents();

            StatusBarTextProvider.InitializeProgressBar(0, (int)BuildStep.Completed, "Building help file");

            try
            {
                cancellationTokenSource = new CancellationTokenSource();

                buildProcess = new BuildProcess(project)
                {
                    ProgressReportProvider = new Progress<BuildProgressEventArgs>(buildProcess_ReportProgress),
                    CancellationToken = cancellationTokenSource.Token,
                };

                await Task.Run(() => buildProcess.Build(), cancellationTokenSource.Token);
            }
            finally
            {
                if(cancellationTokenSource != null)
                {
                    cancellationTokenSource.Dispose();
                    cancellationTokenSource = null;
                }

                StatusBarTextProvider.ResetProgressBar();
                this.SetUIEnabledState(true);
                outputWindow.LogFile = buildProcess.LogFilename;

                if(buildProcess.CurrentBuildStep == BuildStep.Completed && Settings.Default.OpenHelpAfterBuild)
                    miViewHelpFile.PerformClick();

                buildProcess = null;
            }
        }
        /// <summary>
        /// This is called to build a project
        /// </summary>
        /// <param name="project">The project to build</param>
        /// <param name="workingPath">The working path for the project</param>
        /// <returns>Returns true if successful, false if not</returns>
        private bool BuildProject(SandcastleProject project, string workingPath)
        {
            BuildProcess buildProcess;

            lastBuildStep = BuildStep.None;

            builder.ReportProgress("\r\nBuilding {0}", project.Filename);

            try
            {
                // For the plug-in, we'll override some project settings
                project.HtmlHelp1xCompilerPath = new FolderPath(builder.Help1CompilerFolder, true, project);
                project.HtmlHelp2xCompilerPath = new FolderPath(builder.Help2CompilerFolder, true, project);
                project.WorkingPath = new FolderPath(workingPath, true, project);
                project.OutputPath = new FolderPath(workingPath + @"..\PartialBuildLog\", true, project);

                // If the current project has defined OutDir, pass it on to the sub-project.
                string outDir = builder.CurrentProject.MSBuildProject.GetProperty("OutDir").EvaluatedValue;

                if(!String.IsNullOrEmpty(outDir) && outDir != @".\")
                    project.MSBuildOutDir = outDir;

                buildProcess = new BuildProcess(project, PartialBuildType.GenerateReflectionInfo);

                buildProcess.BuildStepChanged += buildProcess_BuildStepChanged;

                // Since this is a plug-in, we'll run it directly rather than in a background thread
                buildProcess.Build();

                // Add the list of the comments files in the other project to this build
                if(lastBuildStep == BuildStep.Completed)
                    foreach(XmlCommentsFile comments in buildProcess.CommentsFiles)
                        builder.CommentsFiles.Insert(0, comments);
            }
            catch(Exception ex)
            {
                throw new BuilderException("VBP0004", String.Format(CultureInfo.InvariantCulture,
                    "Fatal error, unable to compile project '{0}': {1}", project.Filename, ex.ToString()));
            }

            return (lastBuildStep == BuildStep.Completed);
        }
        /// <summary>
        /// This is called to build a project
        /// </summary>
        /// <param name="project">The project to build</param>
        /// <param name="workingPath">The working path for the project</param>
        /// <returns>Returns true if successful, false if not</returns>
        private bool BuildProject(SandcastleProject project, string workingPath)
        {
            BuildProcess buildProcess;

            lastBuildStep = BuildStep.None;

            builder.ReportProgress("\r\nBuilding {0}", project.Filename);

            try
            {
                // For the plug-in, we'll override some project settings
                project.SandcastlePath = new FolderPath(builder.SandcastleFolder, true, project);
                project.HtmlHelp1xCompilerPath = new FolderPath(builder.Help1CompilerFolder, true, project);
                project.HtmlHelp2xCompilerPath = new FolderPath(builder.Help2CompilerFolder, true, project);
                project.WorkingPath = new FolderPath(workingPath, true, project);
                project.OutputPath = new FolderPath(workingPath + @"..\PartialBuildLog\", true, project);

                buildProcess = new BuildProcess(project, true);

                buildProcess.BuildStepChanged += buildProcess_BuildStepChanged;

                // Since this is a plug-in, we'll run it directly rather
                // than in a background thread.
                buildProcess.Build();

                // Add the list of the comments files in the other project to
                // this build.
                foreach(XmlCommentsFile comments in buildProcess.CommentsFiles)
                    builder.CommentsFiles.Insert(0, comments);
            }
            catch(Exception ex)
            {
                throw new BuilderException("VBP0005", String.Format(CultureInfo.InvariantCulture,
                    "Fatal error, unable to compile project '{0}': {1}", project.Filename, ex.ToString()));
            }

            return (lastBuildStep == BuildStep.Completed);
        }
Example #5
0
        //=====================================================================

        /// <summary>
        /// This is used to execute the task and perform the build
        /// </summary>
        /// <returns>True on success or false on failure.</returns>
        public override bool Execute()
        {
            Project msBuildProject = null;
            ProjectInstance projectInstance = null;
            bool removeProjectWhenDisposed = false;
            string line;

            // If canceled already, just return
            if(buildCancelled)
                return false;

            try
            {
                if(!this.AlwaysLoadProject)
                {
                    // Use the current project if possible.  This is preferable as we can make use
                    // of command line property overrides and any other user-defined properties.
                    this.ProjectFile = Path.GetFullPath(this.ProjectFile);

                    // This collection is new to the MSBuild 4.0 API.  If you load a project, it appears
                    // in the collection.  However, if you run MSBuild.exe, it doesn't put the project in
                    // this collection.  As such, we must still resort to reflection to get the executing
                    // project.  I'm leaving this here in case that ever changes as this is preferable to
                    // using Reflection to get at the current project.
                    var matchingProjects = ProjectCollection.GlobalProjectCollection.GetLoadedProjects(
                        this.ProjectFile);

                    if(matchingProjects.Count != 0)
                    {
                        if(matchingProjects.Count != 1)
                            Log.LogWarning(null, "BHT0004", "BHT0004", "SHFB", 0, 0, 0, 0, "Multiple matching " +
                                "projects were found.  Only the first one found will be built.");

                        msBuildProject = matchingProjects.First();
                    }
                    else
                        projectInstance = this.GetCurrentProjectInstance();
                }
            }
            catch(Exception ex)
            {
                // Ignore exceptions but issue a warning and fall back to using
                // the passed project filename instead.
                Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB", 0, 0, 0, 0, "Unable to get executing " +
                    "project: {0}.  The specified project will be loaded but command line property " +
                    "overrides will be ignored.", ex.Message);
            }

            try
            {
                if(msBuildProject == null)
                {
                    removeProjectWhenDisposed = true;

                    if(projectInstance != null)
                    {
                        msBuildProject = new Project(projectInstance.ToProjectRootElement());

                        // ToProjectRootElement() will not add properties in the global collection to the
                        // project.  One problem with this is that command line overrides get missed.  As such,
                        // we'll add them back to the project as long as they are not reserved names and are not
                        // there already.
                        foreach(var p in projectInstance.GlobalProperties)
                            if(!SandcastleProject.restrictedProps.Contains(p.Key) &&
                              !msBuildProject.AllEvaluatedProperties.Any(ep => ep.Name == p.Key))
                                msBuildProject.SetProperty(p.Key, p.Value);

                        msBuildProject.FullPath = this.ProjectFile;
                    }
                    else
                    {
                        if(!File.Exists(this.ProjectFile))
                            throw new BuilderException("BHT0003", "The specified project file does not exist: " +
                                this.ProjectFile);

                        Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB", 0, 0, 0, 0, "Unable to get " +
                            "executing project:  Unable to obtain matching project from the global " +
                            "collection.  The specified project will be loaded but command line property " +
                            "overrides will be ignored.");

                        // Create the project and set the configuration and platform options
                        msBuildProject = new Project(this.ProjectFile);
                    }

                    msBuildProject.SetGlobalProperty(ProjectElement.Configuration, this.Configuration);
                    msBuildProject.SetGlobalProperty(ProjectElement.Platform, this.Platform);

                    // Override the OutDir property if defined for Team Build.  Ignore ".\" as that's our default.
                    if(!String.IsNullOrEmpty(this.OutDir) && this.OutDir != @".\")
                        msBuildProject.SetGlobalProperty(ProjectElement.OutDir, this.OutDir);

                    msBuildProject.ReevaluateIfNecessary();
                }

                // Associate the MSBuild project with a SHFB project instance and build it
                using(sandcastleProject = new SandcastleProject(msBuildProject))
                {
                    buildProcess = new BuildProcess(sandcastleProject);
                    buildProcess.BuildStepChanged += buildProcess_BuildStepChanged;
                    buildProcess.BuildProgress += buildProcess_BuildProgress;

                    // Since this is an MSBuild task, we'll run it directly rather than in a background thread
                    Log.LogMessage(MessageImportance.High, "Building {0}", msBuildProject.FullPath);
                    buildProcess.Build();
                }
            }
            catch(Exception ex)
            {
                Log.LogError(null, "BHT0002", "BHT0002", "SHFB", 0, 0, 0, 0,
                    "Unable to build project '{0}': {1}", msBuildProject.FullPath, ex);
            }
            finally
            {
                // If we loaded it, we must unload it.  If not, it is cached and may cause problems later.
                if(removeProjectWhenDisposed && msBuildProject != null)
                {
                    ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject);
                    ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject.Xml);
                }
            }

            if(this.DumpLogOnFailure && lastBuildStep == BuildStep.Failed)
                using(StreamReader sr = new StreamReader(buildProcess.LogFilename))
                {
                    Log.LogMessage(MessageImportance.High, "Log Content:");

                    do
                    {
                        line = sr.ReadLine();

                        // Don't output the XML elements, just the text
                        if(line != null && (line.Trim().Length == 0 || line.Trim()[0] != '<'))
                            Log.LogMessage(MessageImportance.High, line);

                    } while(line != null);
                }

            return (lastBuildStep == BuildStep.Completed);
        }
Example #6
0
        //=====================================================================
        /// <summary>
        /// This is used to execute the task and perform the build
        /// </summary>
        /// <returns>True on success or false on failure.</returns>
        public override bool Execute()
        {
            Project msBuildProject = null;
            string line;

            try
            {
                if(!alwaysLoadProject)
                {
                    // Use the current project if possible.  This is preferable
                    // as we can make use of command line property overrides
                    // and any other user-defined properties.
                    msBuildProject = this.GetCurrentProject();

                    if(msBuildProject == null)
                    {
                        // We can't use a prior MSBuild version
                        if(isPriorMSBuildVersion)
                        {
                            Log.LogError(null, "BHT0004", "BHT0004", "SHFB",
                                0, 0, 0, 0, "An older MSBuild version is " +
                                "being used.  Unable to build help project.");
                            return false;
                        }

                        Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB",
                            0, 0, 0, 0, "Unable to get executing project: " +
                            "Unable to obtain internal reference.  The " +
                            "specified project will be loaded but command " +
                            "line property overrides will be ignored.");
                    }
                }
            }
            catch(Exception ex)
            {
                // Ignore exceptions but issue a warning and fall back to using
                // the passed project filename instead.
                Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB", 0, 0, 0, 0,
                    "Unable to get executing project: {0}.  The specified " +
                    "project will be loaded but command line property " +
                    "overrides will be ignored.", ex.Message);
            }

            if(msBuildProject == null)
            {
                // Create the project and set the configuration and platform
                // options.
                msBuildProject = new Project(Engine.GlobalEngine);
                msBuildProject.GlobalProperties.SetProperty(
                    ProjectElement.Configuration, configuration);
                msBuildProject.GlobalProperties.SetProperty(
                    ProjectElement.Platform, platform);

                // Override the OutDir property if defined for Team Build
                if(!String.IsNullOrEmpty(outDir))
                    msBuildProject.GlobalProperties.SetProperty(
                        ProjectElement.OutDir, outDir);

                if(!File.Exists(projectFile))
                    throw new BuilderException("BHT0003", "The specified " +
                        "project file does not exist: " + projectFile);

                msBuildProject.Load(projectFile);
            }

            // Load the MSBuild project and associate it with a SHFB
            // project instance.
            sandcastleProject = new SandcastleProject(msBuildProject, true);

            try
            {
                buildProcess = new BuildProcess(sandcastleProject);
                buildProcess.BuildStepChanged +=
                    new EventHandler<BuildProgressEventArgs>(
                        buildProcess_BuildStepChanged);
                buildProcess.BuildProgress +=
                    new EventHandler<BuildProgressEventArgs>(
                        buildProcess_BuildProgress);

                // Since this is an MSBuild task, we'll run it directly rather
                // than in a background thread.
                Log.LogMessage("Building {0}", msBuildProject.FullFileName);
                buildProcess.Build();
            }
            catch(Exception ex)
            {
                Log.LogError(null, "BHT0002", "BHT0002", "SHFB", 0, 0, 0, 0,
                  "Unable to build project '{0}': {1}",
                  msBuildProject.FullFileName, ex);
            }

            if(dumpLogOnFailure && lastBuildStep == BuildStep.Failed)
                using(StreamReader sr = new StreamReader(buildProcess.LogFilename))
                {
                    Log.LogMessage(MessageImportance.High, "Log Content:");

                    do
                    {
                        line = sr.ReadLine();

                        // Don't output the XML elements, just the text
                        if(line != null && (line.Trim().Length == 0 ||
                          line.Trim()[0] != '<'))
                            Log.LogMessage(MessageImportance.High, line);

                    } while(line != null);
                }

            return (lastBuildStep == BuildStep.Completed);
        }