/// <summary> /// Called to reload a project item. /// Reloads a project and its nested project nodes. /// </summary> /// <param name="itemId">Specifies itemid from VSITEMID.</param> /// <param name="reserved">Reserved.</param> /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns> public override int ReloadItem(uint itemId, uint reserved) { #region precondition if (this.IsClosed) { return(VSConstants.E_FAIL); } #endregion NestedProjectNode node = this.NodeFromItemId(itemId) as NestedProjectNode; if (node != null) { object propertyAsObject = node.GetProperty((int)__VSHPROPID.VSHPROPID_HandlesOwnReload); if (propertyAsObject != null && (bool)propertyAsObject) { node.ReloadItem(reserved); } else { this.ReloadNestedProjectNode(node); } return(VSConstants.S_OK); } return(base.ReloadItem(itemId, reserved)); }
/// <summary> /// Links the nested project nodes to the solution. The default implementation parses all nested project nodes and calles AddVirtualProjectEx on them. /// </summary> protected virtual void AddVirtualProjects() { for (HierarchyNode child = this.FirstChild; child != null; child = child.NextSibling) { NestedProjectNode nestedProjectNode = child as NestedProjectNode; if (nestedProjectNode != null) { nestedProjectNode.AddVirtualProject(); } } }
/// <summary> /// Links the nested project nodes to the solution. The default implementation parses all nested project nodes and calles AddVirtualProjectEx on them. /// </summary> protected virtual void AddVirtualProjects() { ThreadHelper.ThrowIfNotOnUIThread(); for (HierarchyNode child = this.FirstChild; child != null; child = child.NextSibling) { NestedProjectNode nestedProjectNode = child as NestedProjectNode; if (nestedProjectNode != null) { nestedProjectNode.AddVirtualProject(); } } }
internal protected void RemoveNestedProjectNodes() { for (HierarchyNode n = this.FirstChild; n != null; n = n.NextSibling) { NestedProjectNode p = n as NestedProjectNode; if (p != null) { p.CloseNestedProjectNode(); } } // We do not care of file changes after this. this.NestedProjectNodeReloader.FileChangedOnDisk -= this.OnNestedProjectFileChangedOnDisk; this.NestedProjectNodeReloader.Dispose(); }
/// <summary> /// Enumerates the nested hierachies that should be added to the build dependency list. /// </summary> /// <returns></returns> public virtual IVsHierarchy[] EnumNestedHierachiesForBuildDependency() { List<IVsHierarchy> nestedProjectList = new List<IVsHierarchy>(); // Add all nested project among projectContainer child nodes for(HierarchyNode child = this.FirstChild; child != null; child = child.NextSibling) { NestedProjectNode nestedProjectNode = child as NestedProjectNode; if(nestedProjectNode != null) { nestedProjectList.Add(nestedProjectNode.NestedHierarchy); } } return nestedProjectList.ToArray(); }
public override int GetNestedHierarchy(UInt32 itemId, ref Guid iidHierarchyNested, out IntPtr ppHierarchyNested, out uint pItemId) { pItemId = VSConstants.VSITEMID_ROOT; ppHierarchyNested = IntPtr.Zero; if (this.FirstChild != null) { for (HierarchyNode n = this.FirstChild; n != null; n = n.NextSibling) { NestedProjectNode p = n as NestedProjectNode; if (p != null && p.ID == itemId) { if (p.NestedHierarchy != null) { IntPtr iunknownPtr = IntPtr.Zero; int returnValue = VSConstants.S_OK; try { iunknownPtr = Marshal.GetIUnknownForObject(p.NestedHierarchy); Marshal.QueryInterface(iunknownPtr, ref iidHierarchyNested, out ppHierarchyNested); } catch (COMException e) { returnValue = e.ErrorCode; } finally { if (iunknownPtr != IntPtr.Zero) { Marshal.Release(iunknownPtr); } } return(returnValue); } break; } } } return(VSConstants.E_FAIL); }
/// <summary> /// This can be called directly or through RunVsTemplateWizard. /// This will clone a template project file and add it as a /// subproject to our hierarchy. /// If you want to create a project for which there exist a /// vstemplate, consider using RunVsTemplateWizard instead. /// </summary> protected internal virtual NestedProjectNode AddNestedProjectFromTemplate(string fileName, string destination, string projectName, ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { // If this is project creation and the template specified a subproject in its project file, this.nestedProjectElement will be used ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; ThreadHelper.ThrowIfNotOnUIThread(); if (elementToUse == null) { // If this is null, this means MSBuild does not know anything about our subproject so add an MSBuild item for it elementToUse = new ProjectElement(this, fileName, ProjectFileConstants.SubProject); } NestedProjectNode node = CreateNestedProjectNode(elementToUse); node.Init(fileName, destination, projectName, creationFlags); // In case that with did not have an existing element, or the nestedProjectelement was null // and since Init computes the final path, set the MSBuild item to that path if (this.nestedProjectElement == null) { string relativePath = node.Url; if (Path.IsPathRooted(relativePath)) { relativePath = this.ProjectFolder; if (!relativePath.EndsWith("/\\", StringComparison.Ordinal)) { relativePath += Path.DirectorySeparatorChar; } relativePath = new Url(relativePath).MakeRelative(new Url(node.Url)); } elementToUse.Rename(relativePath); } this.AddChild(node); return(node); }
/// <summary> /// Reloads a nested project node by deleting it and readding it. /// </summary> /// <param name="node">The node to reload.</param> protected virtual void ReloadNestedProjectNode(NestedProjectNode node) { if (node == null) { throw new ArgumentNullException("node"); } IVsSolution solution = this.GetService(typeof(IVsSolution)) as IVsSolution; if (solution == null) { throw new InvalidOperationException(); } NestedProjectNode newNode = null; try { // (VS 2005 UPDATE) When deleting and re-adding the nested project, // we do not want SCC to see this as a delete and add operation. this.EventTriggeringFlag = ProjectNode.EventTriggering.DoNotTriggerTrackerEvents; // notify SolutionEvents listeners that we are about to add children IVsFireSolutionEvents fireSolutionEvents = solution as IVsFireSolutionEvents; if (fireSolutionEvents == null) { throw new InvalidOperationException(); } ErrorHandler.ThrowOnFailure(fireSolutionEvents.FireOnBeforeUnloadProject(node.NestedHierarchy)); int isDirtyAsInt = 0; this.IsDirty(out isDirtyAsInt); bool isDirty = (isDirtyAsInt == 0) ? false : true; ProjectElement element = node.ItemNode; node.CloseNestedProjectNode(); // Remove from the solution this.RemoveChild(node); // Now readd it try { __VSCREATEPROJFLAGS flags = __VSCREATEPROJFLAGS.CPF_NOTINSLNEXPLR | __VSCREATEPROJFLAGS.CPF_SILENT | __VSCREATEPROJFLAGS.CPF_OPENFILE; newNode = this.AddExistingNestedProject(element, flags); newNode.AddVirtualProject(); } catch (Exception e) { // We get a System.Exception if anything failed, thus we have no choice but catch it. // Exceptions are digested by VS. Show the error if not in automation. if (!Utilities.IsInAutomationFunction(this.Site)) { string message = (String.IsNullOrEmpty(e.Message)) ? SR.GetString(SR.NestedProjectFailedToReload, CultureInfo.CurrentUICulture) : e.Message; string title = string.Empty; OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL; OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK; OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; VsShellUtilities.ShowMessageBox(this.Site, title, message, icon, buttons, defaultButton); } // Do not digest exception. let the caller handle it. If in a later stage this exception is not digested then the above messagebox is not needed. throw; } #if DEBUG IVsHierarchy nestedHierarchy; ErrorHandler.ThrowOnFailure(solution.GetProjectOfUniqueName(newNode.GetMkDocument(), out nestedHierarchy)); Debug.Assert(nestedHierarchy != null && Utilities.IsSameComObject(nestedHierarchy, newNode.NestedHierarchy), "The nested hierrachy was not reloaded correctly."); #endif this.SetProjectFileDirty(isDirty); ErrorHandler.ThrowOnFailure(fireSolutionEvents.FireOnAfterLoadProject(newNode.NestedHierarchy)); } finally { // In this scenario the nested project failed to unload or reload the nested project. We will unload the whole project, otherwise the nested project is lost. // This is similar to the scenario when one wants to open a project and the nested project cannot be loaded because for example the project file has xml errors. // We should note that we rely here that if the unload fails then exceptions are not digested and are shown to the user. if (newNode == null || newNode.NestedHierarchy == null) { ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement((uint)__VSSLNCLOSEOPTIONS.SLNCLOSEOPT_UnloadProject | (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, this, 0)); } else { this.EventTriggeringFlag = ProjectNode.EventTriggering.TriggerAll; } } }
/// <summary> /// Reloads a nested project node by deleting it and readding it. /// </summary> /// <param name="node">The node to reload.</param> protected virtual void ReloadNestedProjectNode(NestedProjectNode node) { if(node == null) { throw new ArgumentNullException("node"); } IVsSolution solution = this.GetService(typeof(IVsSolution)) as IVsSolution; if(solution == null) { throw new InvalidOperationException(); } NestedProjectNode newNode = null; try { // (VS 2005 UPDATE) When deleting and re-adding the nested project, // we do not want SCC to see this as a delete and add operation. this.EventTriggeringFlag = SuppressEvents.Tracker; // notify SolutionEvents listeners that we are about to add children IVsFireSolutionEvents fireSolutionEvents = solution as IVsFireSolutionEvents; if(fireSolutionEvents == null) { throw new InvalidOperationException(); } ErrorHandler.ThrowOnFailure(fireSolutionEvents.FireOnBeforeUnloadProject(node.NestedHierarchy)); int isDirtyAsInt = 0; this.IsDirty(out isDirtyAsInt); bool isDirty = (isDirtyAsInt == 0) ? false : true; ProjectElement element = node.ItemNode; node.CloseNestedProjectNode(); // Remove from the solution this.RemoveChild(node); // Now readd it try { __VSCREATEPROJFLAGS flags = __VSCREATEPROJFLAGS.CPF_NOTINSLNEXPLR | __VSCREATEPROJFLAGS.CPF_SILENT | __VSCREATEPROJFLAGS.CPF_OPENFILE; newNode = this.AddExistingNestedProject(element, flags); newNode.AddVirtualProject(); } catch(Exception e) { // We get a System.Exception if anything failed, thus we have no choice but catch it. // Exceptions are digested by VS. Show the error if not in automation. if(!Utilities.IsInAutomationFunction(this.Site)) { string message = (String.IsNullOrEmpty(e.Message)) ? SR.GetString(SR.NestedProjectFailedToReload, CultureInfo.CurrentUICulture) : e.Message; string title = string.Empty; OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL; OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK; OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; VsShellUtilities.ShowMessageBox(this.Site, title, message, icon, buttons, defaultButton); } // Do not digest exception. let the caller handle it. If in a later stage this exception is not digested then the above messagebox is not needed. throw; } #if DEBUG IVsHierarchy nestedHierarchy; ErrorHandler.ThrowOnFailure(solution.GetProjectOfUniqueName(newNode.GetMKDocument(), out nestedHierarchy)); Debug.Assert(nestedHierarchy != null && Utilities.IsSameComObject(nestedHierarchy, newNode.NestedHierarchy), "The nested hierrachy was not reloaded correctly."); #endif this.SetProjectFileDirty(isDirty); ErrorHandler.ThrowOnFailure(fireSolutionEvents.FireOnAfterLoadProject(newNode.NestedHierarchy)); } finally { // In this scenario the nested project failed to unload or reload the nested project. We will unload the whole project, otherwise the nested project is lost. // This is similar to the scenario when one wants to open a project and the nested project cannot be loaded because for example the project file has xml errors. // We should note that we rely here that if the unload fails then exceptions are not digested and are shown to the user. if(newNode == null || newNode.NestedHierarchy == null) { ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement((uint)__VSSLNCLOSEOPTIONS.SLNCLOSEOPT_UnloadProject | (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, this.InteropSafeIVsHierarchy, 0)); } else { this.EventTriggeringFlag = SuppressEvents.None; } } }
internal VisualStudio_Project_Samples_NestedProjectNodeAccessor(NestedProjectNode target) : base(target, m_privateType) { }