/// <summary> /// Notifies all of the registered listeners that a node was removed from the hierarchy. /// </summary> /// <param name="node">The node that was removed.</param> public void OnItemDeleted(Node node) { Tracer.VerifyNonNullArgument(node, "node"); // Let all of our listeners know that an item was deleted. Tracer.WriteLine(classType, "OnItemDeleted", Tracer.Level.Information, "Notifying all of our listeners that '{0}' was removed from the hierarchy.", node.Caption); // There are some cases where the collection is changed while we're iterating it, // for example when the project node is removed. To be safe, we'll create a copy // of the collection and iterate over that. We just want a shallow copy, though, // and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsHierarchyEvents eventItem in clone) { try { eventItem.OnItemDeleted(node.HierarchyId); } catch (Exception e) { Tracer.WriteLine(classType, "OnItemDeleted", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } }
/// <summary> /// Notifies all of the listeners that a project has begun building. /// </summary> /// <returns>true if the build should continue; false if one or more of the listeners requested /// that the build should be canceled.</returns> public bool OnBuildBegin() { bool continueBuilding = true; // Let all of our listeners know that the build has started. Tracer.WriteLineInformation(classType, "OnBuildBegin", "Notifying all of our listeners that the build has started."); // There are some cases where the collection is changed while we're iterating it. // To be safe, we'll create a copy of the collection and iterate over that. // We just want a shallow copy, though, and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsBuildStatusCallback eventItem in clone) { try { int continueFlag = Convert.ToInt32(continueBuilding); eventItem.BuildBegin(ref continueFlag); if (continueFlag == 0) { continueBuilding = false; } } catch (Exception e) { Tracer.WriteLine(classType, "OnBuildBegin", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } return(continueBuilding); }
/// <summary> /// Notifies all of the registered listeners that a node was added to the hierarchy. /// </summary> /// <param name="node">The node that was added.</param> public void OnItemAdded(Node node) { Tracer.VerifyNonNullArgument(node, "node"); // Let all of our listeners know that an item was added. Tracer.WriteLine(classType, "OnItemAdded", Tracer.Level.Information, "Notifying all of our listeners that '{0}' was added to the hierarchy.", node.Caption); // There are some cases where the collection is changed while we're iterating it. // To be safe, we'll create a copy of the collection and iterate over that. // We just want a shallow copy, though, and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsHierarchyEvents eventItem in clone) { uint parentId = (node.Parent != null ? node.Parent.HierarchyId : NativeMethods.VSITEMID_NIL); uint previousSiblingId = (node.PreviousSibling != null ? node.PreviousSibling.HierarchyId : NativeMethods.VSITEMID_NIL); uint nodeId = node.HierarchyId; try { eventItem.OnItemAdded(parentId, previousSiblingId, nodeId); } catch (Exception e) { Tracer.WriteLine(classType, "OnItemAdded", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } }
/// <summary> /// Notifies all of the listeners that a configuration name has been changed. /// </summary> /// <param name="oldName">The old name of the configuration that was changed.</param> /// <param name="newName">The new name of the configuration that was changed.</param> public void OnCfgNameRenamed(string oldName, string newName) { Tracer.VerifyStringArgument(oldName, "oldName"); Tracer.VerifyStringArgument(newName, "newName"); // Let all of our listeners know that the hierarchy needs to be refreshed. Tracer.WriteLine(classType, "OnCfgNameRenamed", Tracer.Level.Information, "Notifying all of our listeners that the configuration '{0}' has been renamed to '{1}'.", oldName, newName); // There are some cases where the collection is changed while we're iterating it. // To be safe, we'll create a copy of the collection and iterate over that. // We just want a shallow copy, though, and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsCfgProviderEvents eventItem in clone) { try { eventItem.OnCfgNameRenamed(oldName, newName); } catch (Exception e) { Tracer.WriteLine(classType, "OnCfgNameRenamed", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } }
/// <summary> /// Notifies all of the listeners that a project has finished building. /// </summary> /// <param name="success">true if the build operation completed successfully. On an up-to-date check, /// <paramref name="success"/> must be set to true when the project configuration is up to date and /// false when the project configuration is not up to date.</param> public void OnBuildEnd(bool success) { // Let all of our listeners know that the build has ended. if (success) { Tracer.WriteLineInformation(classType, "OnBuildEnd", "Notifying all of our listeners that the build has ended successfully."); } else { Tracer.WriteLineInformation(classType, "OnBuildEnd", "Notifying all of our listeners that the build has ended with errors."); } int successFlag = Convert.ToInt32(success); // There are some cases where the collection is changed while we're iterating it. // To be safe, we'll create a copy of the collection and iterate over that. // We just want a shallow copy, though, and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsBuildStatusCallback eventItem in clone) { try { eventItem.BuildEnd(successFlag); } catch (Exception e) { Tracer.WriteLine(classType, "OnBuildEnd", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } }
protected uint Add(object listener) { Tracer.VerifyNonNullArgument(listener, "listener"); Tracer.WriteLine(classType, "Add", Tracer.Level.Information, "Adding an event listener to the {0} collection: Cookie={1}", this.GetType().Name, nextCookie); this.listeners.Add(nextCookie, listener); nextCookie++; return(nextCookie - 1); }
/// <summary> /// Initializes this package. /// </summary> private void Initialize() { int hr = NativeMethods.S_OK; // If we have any services to proffer, let's do it now. if (this.services != null) { IProfferService ps = (IProfferService)this.GetService(typeof(IProfferService)); Tracer.Assert(ps != null, "We have services to proffer, but can't get an instance of IProfferService."); if (ps != null) { foreach (DictionaryEntry entry in this.services) { ProfferedService service = entry.Value as ProfferedService; if (service != null) { Type serviceType = (Type)entry.Key; Guid serviceGuid = serviceType.GUID; uint cookie; hr = ps.ProfferService(ref serviceGuid, this, out cookie); service.Cookie = cookie; if (NativeMethods.Failed(hr)) { string message = this.Context.NativeResources.GetString(ResId.IDS_E_FAILEDTOPROFFERSERVICE, serviceType.FullName); Tracer.Fail(message); throw new COMException(message, hr); } } } } } // Create the Project Factory and register our project types. Tracer.WriteLineInformation(classType, "Initialize", "Creating the project factory and registering our project types."); IVsRegisterProjectTypes regProjTypes = (IVsRegisterProjectTypes)this.Context.ServiceProvider.GetServiceOrThrow(typeof(SVsRegisterProjectTypes), typeof(IVsRegisterProjectTypes), classType, "Initialize"); this.projectFactory = this.CreateProjectFactory(); Guid projectGuid = this.ProjectTypeGuid; hr = regProjTypes.RegisterProjectType(ref projectGuid, this.projectFactory, out this.projectCookie); if (NativeMethods.Succeeded(hr)) { Tracer.WriteLine(classType, "Initialize", Tracer.Level.Information, "Successfully registered our project types."); } else { Tracer.Fail("Failed to register the Wix Project type. HRESULT = 0x{0}", hr.ToString("x")); } }
public void Remove(uint cookie) { if (this.listeners.ContainsKey(cookie)) { this.listeners.Remove(cookie); Tracer.WriteLine(classType, "Remove", Tracer.Level.Information, "Removing an event listener from the {0} collection: Cookie={1}", this.GetType().Name, cookie); } else { string message = "Attempting to unadvise an unregistered event sink. Cookie=" + cookie; Tracer.Fail(message); message = Package.Instance.Context.NativeResources.GetString(ResourceId.IDS_E_UNADVISINGUNREGISTEREDEVENTSINK, cookie); Package.Instance.Context.ShowErrorMessageBox(message); } }
/// <summary> /// Called right after the node is added to the collection. /// </summary> /// <param name="index">The index of the item added to the collection.</param> /// <param name="value">The <see cref="Node"/> just added to the collection.</param> protected override void OnAddComplete(int index, object value) { Node node = (Node)value; // Set the node's parent to us. node.Parent = this.Parent; // Add the item to our lookup tables. Tracer.Assert(!this.idTable.ContainsKey(node.HierarchyId), "Something's wrong with our comparer."); this.idTable[node.HierarchyId] = node; Tracer.Assert(!this.pathTable.ContainsKey(node.AbsolutePath), "This node has already been added."); this.pathTable[node.AbsolutePath] = node; // This is useful information to trace, so we'll use the Hierarchy category and the Information level, // which will allow this to be traced by default. Tracer.WriteLine(classType, "OnAddComplete", Tracer.Level.Information, "Added '{0}' to the hierarchy.", node.ToString()); }
int IVsProject3.OpenItemWithSpecific(uint itemid, uint grfEditorFlags, ref Guid rguidEditorType, string pszPhysicalView, ref Guid rguidLogicalView, IntPtr punkDocDataExisting, out IVsWindowFrame ppWindowFrame) { ppWindowFrame = null; FileNode node = this.GetNode(itemid, false) as FileNode; if (node == null) { Tracer.Fail("The framework is calling us in an unexpected way because we report that we don't own the item '{0}' but Visual Studio thinks we do.", itemid); return(NativeMethods.E_UNEXPECTED); } // Map the raw logical view guid to one of our predetermined ones. VsLogicalView view; if (!VsLogicalView.TryFromGuid(rguidLogicalView, out view)) { Tracer.WriteLine(classType, "IVsProject3.OpenItemWithSpecific", Tracer.Level.Warning, "We're getting a logical view that we don't understand: '{0}'. Using the primary view instead.", rguidLogicalView.ToString("B")); view = VsLogicalView.Primary; } // Do we open with the standard or a specific editor? bool openWithSpecificEditor = ((((__VSSPECIFICEDITORFLAGS)grfEditorFlags) & __VSSPECIFICEDITORFLAGS.VSSPECIFICEDITOR_UseEditor) == __VSSPECIFICEDITORFLAGS.VSSPECIFICEDITOR_UseEditor); // Tell the node to open itself. if (openWithSpecificEditor) { ppWindowFrame = node.OpenWithSpecificEditor(view, punkDocDataExisting, pszPhysicalView, rguidEditorType); } else { ppWindowFrame = node.OpenWithStandardEditor(view, punkDocDataExisting); } return(NativeMethods.S_OK); }
/// <summary> /// Notifies all of the listeners that the specified node and all of its children need to be invalidated. /// </summary> /// <param name="parent">The parent node that needs to be invalidated.</param> public void OnInvalidateItems(Node parent) { Tracer.VerifyNonNullArgument(parent, "parent"); // Let all of our listeners know that the hierarchy needs to be refreshed. Tracer.WriteLine(classType, "OnInvalidateItems", Tracer.Level.Information, "Notifying all of our listeners that the hierarchy needs to be refreshed from '{0}'.", parent.Caption); // There are some cases where the collection is changed while we're iterating it. // To be safe, we'll create a copy of the collection and iterate over that. // We just want a shallow copy, though, and not a deep (Clone) copy. ArrayList clone = new ArrayList(this.Values); foreach (IVsHierarchyEvents eventItem in clone) { try { eventItem.OnInvalidateItems(parent.HierarchyId); } catch (Exception e) { Tracer.WriteLine(classType, "OnInvalidateItems", Tracer.Level.Warning, "There was an exception in one of the listener's event handling code: {0}", e.ToString()); } } }
/// <summary> /// Loads a project file from disk. /// </summary> /// <param name="filePath">The absolute path of the project file to load.</param> /// <returns>true if the project file was loaded correctly; otherwise, false.</returns> public bool Load(string filePath) { Tracer.VerifyStringArgument(filePath, "filePath"); // Create a new project. this.project = this.CreateProject(this); // Set the project's file path to the one being loaded in. Do this first in case we have // to make the project unavailable it can still display the correct caption in Solution Explorer. this.Project.FilePath = filePath; // Make sure the file exists. if (!File.Exists(filePath)) { if (!this.SilentFailures) { string message = SconceStrings.FileDoesNotExist(filePath); Package.Instance.Context.ShowErrorMessageBox(message); } this.Project.Unavailable = true; Tracer.WriteLine(classType, "Load", Tracer.Level.Warning, "The project file '{0}' does not exist.", filePath); return(false); } try { using (StreamReader stream = new StreamReader(filePath)) { XmlTextReader reader = new XmlTextReader(stream); reader.WhitespaceHandling = WhitespaceHandling.None; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(reader); XmlNode node = xmlDoc.DocumentElement; // <VisualStudioProject> if (!this.VerifyNode(node, ElementNames.VisualStudioProject)) { this.Project.Unavailable = true; return(false); } node = node.FirstChild; if (!this.ReadProjectNode(node)) { this.Project.Unavailable = true; return(false); } } } catch (XmlException e) { if (!this.SilentFailures) { string projectFileName = Path.GetFileName(filePath); string title = Package.Instance.Context.NativeResources.GetString(ResId.IDS_E_INVALIDPROJECTFILE_TITLE); string message = Package.Instance.Context.NativeResources.GetString(ResId.IDS_E_INVALIDPROJECTFILE, projectFileName); Package.Instance.Context.ShowErrorMessageBox(title, message); } this.Project.Unavailable = true; Tracer.Fail("There was an error parsing '{0}': {1}", filePath, e.ToString()); return(false); } // Once the project has been loaded, it's not dirty anymore. this.Project.ClearDirty(); return(true); }
public static void TraceRunningDocuments() { // Get the RDT (Running Document Table) IVsRunningDocumentTable rdt = Package.Instance.Context.ServiceProvider.GetService(typeof(IVsRunningDocumentTable)) as IVsRunningDocumentTable; if (rdt == null) { Tracer.WriteLineWarning(classType, "TraceRunningDocuments", "Cannot get an instance of IVsRunningDocumentTable to use for enumerating the running documents."); return; } // Get the enumerator for the currently running documents. IEnumRunningDocuments enumerator; int hr = rdt.GetRunningDocumentsEnum(out enumerator); if (NativeMethods.Failed(hr)) { Tracer.WriteLineWarning(classType, "TraceRunningDocuments", "Cannot get an instance of IEnumRunningDocuments to use for enumerating the running documents."); return; } // Enumerate. StringCollection traceLines = new StringCollection(); uint[] cookies = new uint[1]; uint fetchCount; while (true) { hr = enumerator.Next(1, cookies, out fetchCount); if (NativeMethods.Failed(hr)) { Tracer.WriteLineWarning(classType, "TraceRunningDocuments", "The enumeration failed for the running documents. Hr=0x{0:X}", hr); return; } if (fetchCount == 0) { break; } uint cookie = cookies[0]; // We shouldn't be getting a nil cookie. if (cookie == DocumentInfo.NullCookie) { Tracer.WriteLineWarning(classType, "TraceRunningDocuments", "There is a null cookie value in the RDT, which shouldn't be happening."); } else { // Now we have a document cookie, so let's get some information about it. DocumentInfo docInfo = Package.Instance.Context.RunningDocumentTable.FindByCookie(cookie); string traceMessage; if (docInfo == null) { traceMessage = PackageUtility.SafeStringFormatInvariant("The document with cookie '{0}' could not be found in the RDT. There's something weird going on.", cookie); } else { // Here's where we actually do the trace finally. traceMessage = PackageUtility.SafeStringFormatInvariant("RDT document: Cookie={0} Path={1} IsOpen={2} IsDirty={3}", docInfo.Cookie, docInfo.AbsolutePath, docInfo.IsOpen, docInfo.IsDirty); } // We don't want to trace immediately because we want all of these lines to appear together. If we // trace immediately, then the messages will be split up. traceLines.Add(traceMessage); } } // Now trace all of the messages at once. foreach (string traceMessage in traceLines) { Tracer.WriteLine(classType, "TraceRunningDocuments", Tracer.Level.Information, traceMessage); } }