/// <summary> /// Checks whether the proposed caption already exists, meaning that there is not an existing file /// or folder at the root path or that there is not already a sibling hierarchy item with the same name. /// </summary> /// <param name="newCaption">The proposed caption.</param> /// <param name="newPath">The proposed new absolute file path.</param> /// <remarks>The method throws an exception if the caption already exists.</remarks> private void VerifyCaptionDoesNotExist(string newCaption, string newPath) { bool valid = true; // Make sure there isn't already a sibling with the same caption. The root node has no siblings. if (this.Parent != null) { foreach (Node sibling in this.Parent.Children) { bool thisIsSibling = Object.ReferenceEquals(sibling, this); bool captionsEqual = (PackageUtility.FileStringEquals(newCaption, sibling.Caption)); // We can have a file system node that is the same name as a virtual node. // For example, we can name a file/folder "Library References" if we want, // even though that is already in the hierarchy. bool isExactlyOneVirtual = ((this.IsVirtual && !sibling.IsVirtual) || (!this.IsVirtual && sibling.IsVirtual)); if (!thisIsSibling && captionsEqual && !isExactlyOneVirtual) { valid = false; break; } } } if (valid) { // Now check to see if the file system already contains a file/folder by the same name. valid = ((this.IsFile && !File.Exists(newPath)) || (this.IsFolder && !Directory.Exists(newPath))); } if (!valid) { Tracer.WriteLineInformation(classType, "VerifyCaption", "An existing file or folder named '{0}' already exists on the disk.", newCaption); throw new InvalidOperationException(SconceStrings.ErrorItemAlreadyExistsOnDisk(newCaption)); } }
/// <summary> /// Throws an <see cref="InvalidOperationException"/> informing the user that a critical service is missing and to /// try to repair the Visual Studio installation. /// </summary> /// <param name="classType">The type of the class containing the method.</param> /// <param name="methodName">The name of the method that is being entered.</param> /// <param name="serviceType">An object that specifies the type of service object that was requested but failed.</param> /// <remarks>Also logs a failure message in the trace log and asserts in debug mode.</remarks> public void ThrowFailedServiceException(Type classType, string methodName, Type serviceType) { string serviceTypeName = serviceType.Name; Tracer.Fail("Cannot get an instance of {0}", serviceTypeName); throw new InvalidOperationException(SconceStrings.ErrorMissingService(serviceTypeName)); }
/// <summary> /// Gets a string from the resource file and formats it using the specified arguments. /// </summary> /// <param name="name">The resource identifier of the string to retrieve.</param> /// <param name="args">An array of objects to use in the formatting. Can be null or empty.</param> /// <returns>A formatted string from the resource file.</returns> public string GetString(string name, params object[] args) { string returnString = this.missingManifestString; // If we previously tried to get a string from the resource file and we had a // MissingManifestResourceException, then we don't want to try again. Exceptions // are expensive especially when we could be getting lots of strings. if (!this.isMissingManifest) { try { // First give the subclass a chance to retrieve the string if (this.IsStringDefined(name)) { returnString = this.manager.GetString(name, CultureInfo.CurrentUICulture); } //\ Try getting the string from our assembly if the subclass can't handle it else if (SconceStrings.IsValidStringName(name)) { returnString = thisAssemblyManager.GetString(name, CultureInfo.CurrentUICulture); } else { Tracer.WriteLineWarning(classType, "GetString", "The string id '{0}' is not defined.", name); returnString = name; } // Format the message if there are arguments specified. Note that we format // using the CurrentCulture and not the CurrentUICulture (although in almost all // cases it will be the same). if (returnString != null && args != null && args.Length > 0) { returnString = String.Format(CultureInfo.CurrentCulture, returnString, args); } } catch (MissingManifestResourceException e) { this.isMissingManifest = true; Tracer.Fail("The resource cannot be found in the assembly: {0}", e); } } return(returnString); }
//========================================================================================== // Properties //========================================================================================== #endregion #region Methods //========================================================================================== // Methods //========================================================================================== /// <summary> /// Returns a value indicating whether the specified name is a defined string resource name. /// </summary> /// <param name="name">The resource identifier to check.</param> /// <returns>true if the string identifier is defined in our assembly; otherwise, false.</returns> public virtual bool IsStringDefined(string name) { return(SconceStrings.IsValidStringName(name)); }
public static void AppendConsultTraceMessage(ref string message) { message += SconceStrings.ConsultTraceLog(Tracer.LogPath); }
/// <summary> /// Opens the standard editor for this file type in Visual Studio. /// </summary> /// <param name="logicalView">The type of view in which to open the document.</param> /// <param name="existingDocumentData"> /// Passed through to the IVsUIShellOpenDocument.OpenStandardEditor or OpenSpecificEditor, which /// will then determine if the document is already opened and reused the open window. /// </param> /// <param name="physicalView"> /// Name of the physical view if we're opening with a specific editor. Not used if opening with a standard editor. /// </param> /// <param name="specificEditor">The GUID of the specific registered editor to use to open this node.</param> /// <returns>The <see cref="IVsWindowFrame"/> object that contains the opened document.</returns> private IVsWindowFrame Open(VsLogicalView logicalView, IntPtr existingDocumentData, Guid specificEditor, string physicalView) { Tracer.VerifyNonNullArgument(logicalView, "logicalView"); // Check to see if the file exists before we try to open it. if (!File.Exists(this.AbsolutePath)) { Context.ShowErrorMessageBox(SconceStrings.FileDoesNotExist(this.AbsolutePath)); return(null); } IVsWindowFrame windowFrame; Guid logicalViewGuid = logicalView.Value; Guid editorTypeGuid = specificEditor; bool useSpecificEditor = (specificEditor != Guid.Empty); int hr; // Get a IVsUIShellOpenDocument object so that we can use it to open the document. IVsUIShellOpenDocument vsUIShellOpenDocument = (IVsUIShellOpenDocument)this.ServiceProvider.GetServiceOrThrow(typeof(SVsUIShellOpenDocument), typeof(IVsUIShellOpenDocument), classType, "Open"); // Open the document. if (useSpecificEditor) { hr = vsUIShellOpenDocument.OpenSpecificEditor( 0, this.CanonicalName, ref editorTypeGuid, physicalView, ref logicalViewGuid, this.Caption, (IVsUIHierarchy)this.Hierarchy, this.HierarchyId, existingDocumentData, (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)Package.Instance, out windowFrame); } else { hr = vsUIShellOpenDocument.OpenStandardEditor( unchecked ((uint)__VSOSEFLAGS.OSE_ChooseBestStdEditor), this.CanonicalName, ref logicalViewGuid, this.Caption, (IVsUIHierarchy)this.Hierarchy, this.HierarchyId, existingDocumentData, (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)Package.Instance, out windowFrame); } string editorTypeName = useSpecificEditor ? "specific" : "standard"; if (NativeMethods.Succeeded(hr)) { Tracer.WriteLineInformation(classType, "Open", "Succeeded in opening '{0}' with a {1} editor.", this.AbsolutePath, editorTypeName); if (windowFrame != null) { // Get the document cookie and cache it. object pvar; hr = windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocCookie, out pvar); NativeMethods.ThrowOnFailure(hr); // pvar is an int, but we need a uint. We get an error if we try to immediately cast to uint // without first casting to an int. uint cookie = unchecked ((uint)(int)pvar); this.SetDocumentCookie(cookie); Tracer.WriteLineInformation(classType, "Open", "Document '{0}' has a cookie value of {1}", this.AbsolutePath, cookie); // Show the window frame of the open document. The documentation says we don't need to do this, but the reality is different. hr = windowFrame.Show(); Tracer.Assert(NativeMethods.Succeeded(hr), "Error in IVsWindowFrame.Show(): 0x{0:x}", hr); // Trace the running documents. VsHelperMethods.TraceRunningDocuments(); } else { Tracer.Fail("Open succeeded but we were returned a null IVsWindowFrame so we can't show the document."); } } else if (hr == NativeMethods.OLE_E_PROMPTSAVECANCELLED) { Tracer.WriteLineInformation(classType, "Open", "The user canceled out of the open dialog box."); } else { Tracer.Fail("Failed to open '{0}' with a {1} editor. Hr=0x{2:x}", this.AbsolutePath, editorTypeName, hr); NativeMethods.ThrowOnFailure(hr); } return(windowFrame); }
/// <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); }