/// <summary>
        /// Sets up the build system in preparation for a build operation (clean, build, rebuild) and calls
        /// the operation delegate at the appropriate place. This also handles any errors that occur and
        /// makes sure the build isn't in a weird state.
        /// </summary>
        /// <param name="outputPane">The window to output build messages to.</param>
        /// <param name="operationDelegate">The method to call after setup has occurred and before cleanup.</param>
        /// <returns>true if the operation was successful; otherwise, false.</returns>
        private bool BuildOperation(IVsOutputWindowPane outputPane, InternalBuildOperation operationDelegate)
        {
            Tracer.VerifyNonNullArgument(outputPane, "outputPane");

            if (!this.PrepareBuild(outputPane))
            {
                return(false);
            }

            bool successful = false;

            try
            {
                successful = operationDelegate(outputPane);
            }
            catch (Exception e)
            {
                if (ErrorUtility.IsExceptionUnrecoverable(e))
                {
                    throw;
                }

                this.WriteLineToOutputWindow("There was an error while building the project.");

                // Append the "Consult the trace log message"
                string message = String.Empty;
                PackageUtility.AppendConsultTraceMessage(ref message);
                if (!String.IsNullOrEmpty(message))
                {
                    this.WriteLineToOutputWindow(message);
                }

                this.WriteLineToOutputWindow("Exception: {0}", e);
                this.WriteLineToOutputWindow();

                successful = false;
            }
            finally
            {
                this.FinishBuild(successful);
            }

            return(successful);
        }
Example #2
0
        /// <summary>
        /// Does the actual work of changing the caption after all of the verifications have been done
        /// that it's Ok to move the file.
        /// </summary>
        /// <param name="newCaption">The new caption.</param>
        /// <param name="newPath">The new absolute path.</param>
        public override void MoveNodeOnCaptionChange(string newCaption, string newPath)
        {
            string oldCaption            = this.Caption;
            string oldPath               = this.AbsolutePath;
            string oldRelativePath       = this.RelativePath;
            bool   updatedWindowCaptions = false;
            bool   removedNode           = false;
            Node   newNode               = null;

            // If we are currently selected, cache the value so we can restore the selection
            // after the addition.
            bool wasSelected = this.Selected;

            // Tell the environment to stop listening to file change events on the old file.
            using (FileChangeNotificationSuspender notificationSuspender = new FileChangeNotificationSuspender(oldPath))
            {
                // Make sure the environment says we can start the rename.
                if (!this.Hierarchy.AttachedProject.Tracker.CanRenameFile(oldPath, newPath))
                {
                    return;
                }

                // Move the file on the file system to match the new name.
                if (!this.IsVirtual && File.Exists(oldPath) && !File.Exists(newPath))
                {
                    Tracer.WriteLineInformation(classType, "MoveNodeOnCaptionChange", "Renaming the file '{0}' to '{1}'.", oldPath, newPath);
                    string newDirectoryName = Path.GetDirectoryName(newPath);
                    if (!Directory.Exists(newDirectoryName))
                    {
                        Directory.CreateDirectory(newDirectoryName);
                    }
                    File.Move(oldPath, newPath);
                }

                try
                {
                    // Update all of the windows that currently have this file opened in an editor.
                    this.UpdateOpenWindowCaptions(newCaption);
                    updatedWindowCaptions = true;

                    // We have to remove the node and re-add it so that we can have the sorting preserved.
                    // Also, if the extension has changed then we'll have to recreate a new type-specific
                    // FileNode. The easy way is to remove ourself from the project then tell the project
                    // to add an existing file.

                    string newRelativePath = PackageUtility.MakeRelative(this.Hierarchy.RootNode.AbsoluteDirectory, newPath);

                    // Remove ourself from the hierarchy.
                    this.Parent.Children.Remove(this);
                    removedNode = true;

                    // We have now been removed from the hierarchy. Do NOT call any virtual methods or
                    // methods that depend on our state after this point.

                    // Re-add ourself as a new incarnation (different object). Our life ends here.
                    newNode = this.Hierarchy.AddExistingFile(newRelativePath, true);

                    if (newNode != null)
                    {
                        // We need to set our hierarchy Id to match the new hierachy Id in case Visual Studio
                        // calls back into us for something.
                        this.SetHierarchyId(newNode.HierarchyId);

                        // Select the new node if we were previously selected.
                        if (wasSelected)
                        {
                            newNode.Select();
                        }

                        // Tell the RDT to rename the document.
                        Context.RunningDocumentTable.RenameDocument(oldPath, newPath, newNode.HierarchyId);
                    }
                }
                catch (Exception e)
                {
                    if (ErrorUtility.IsExceptionUnrecoverable(e))
                    {
                        throw;
                    }

                    // Rollback the file move
                    Tracer.WriteLineWarning(classType, "MoveNodeOnCaptionChange", "There was an error in renaming the document. Exception: {0}", e);
                    File.Move(newPath, oldPath);

                    // Remove the node that we just added.
                    if (newNode != null)
                    {
                        newNode.RemoveFromProject();
                    }

                    // Re-add a new node since we've already removed the old node.
                    if (removedNode || this.Parent == null)
                    {
                        newNode = this.Hierarchy.AddExistingFile(oldRelativePath, true);
                        this.SetHierarchyId(newNode.HierarchyId);
                        if (wasSelected)
                        {
                            newNode.Select();
                        }
                    }

                    // Rollback the caption update on open windows
                    if (updatedWindowCaptions)
                    {
                        this.UpdateOpenWindowCaptions(oldCaption);
                    }

                    // Rethrow the exception
                    throw;
                }

                // Tell the environment that we're done renaming the document.
                this.Hierarchy.AttachedProject.Tracker.OnFileRenamed(oldPath, newPath);

                // Update the property browser.
                IVsUIShell vsUIShell = (IVsUIShell)this.Hierarchy.ServiceProvider.GetServiceOrThrow(typeof(SVsUIShell), typeof(IVsUIShell), classType, "MoveNodeOnCaptionChange");
                vsUIShell.RefreshPropertyBrowser(0);
            }
        }