From: Daniel C. \(kzu\) <dca...@us...> - 2004-10-21 20:42:17
|
Update of /cvsroot/mvp-xml/Design/v1/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28388/v1/src Added Files: DteHelper.cs ProjectInstaller.cs Log Message: --- NEW FILE: ProjectInstaller.cs --- #region using using System; using System.Collections; using System.ComponentModel; using System.Configuration.Install; using System.Reflection; using System.Runtime.InteropServices; #endregion using namespace Mvp.Xml.Design { /// <summary> /// Registers the project with COM. /// </summary> [RunInstaller(true)] [System.ComponentModel.DesignerCategory("Code")] public class ProjectInstaller : System.Configuration.Install.Installer { public override void Install(IDictionary stateSaver) { base.Install(stateSaver); new RegistrationServices().RegisterAssembly( Assembly.GetExecutingAssembly(), AssemblyRegistrationFlags.SetCodeBase); } public override void Rollback(IDictionary savedState) { base.Rollback (savedState); new RegistrationServices().UnregisterAssembly( Assembly.GetExecutingAssembly()); } public override void Uninstall(IDictionary savedState) { base.Uninstall (savedState); new RegistrationServices().UnregisterAssembly( Assembly.GetExecutingAssembly()); } } } --- NEW FILE: DteHelper.cs --- #region using using System; using System.IO; using EnvDTE; using VSLangProj; #endregion using namespace Mvp.Xml.Design { /// <summary> /// Provides utility methods for working with the DTE. /// </summary> internal sealed class DteHelper { private DteHelper() { } #region BuildPath public static string BuildPath(SelectedItem toSelectedItem) { if (toSelectedItem.ProjectItem != null) { return BuildPath(toSelectedItem.ProjectItem); } else if (toSelectedItem.Project != null) { return BuildPath(toSelectedItem.Project); } return toSelectedItem.Name; } public static string BuildPath(Project toProject) { string path = ""; // Solution folders are exposed with the same kind as solution items. // This eases compatibility with VS2003 in the future. if (toProject.Kind == Constants.vsProjectKindSolutionItems) { string folder = ""; foreach (Project project in toProject.DTE.Solution.Projects) { folder = project.Name; // Only build the path if it's not the same top-level project. if (project == toProject) { break; } else if (BuildPathToFolder(project, toProject, ref folder)) { break; } } path = folder + path; } else { if (toProject.ParentProjectItem == null) { return toProject.Name; } else { string folder = ""; foreach (Project project in toProject.DTE.Solution.Projects) { folder = project.Name; // Only build the path if it's not the same top-level project. if (project == toProject) { break; } else if (BuildPathToFolder(project, toProject, ref folder)) { break; } } path = folder + path; } } return path; } public static string BuildPath(ProjectItem toItem) { string path = ""; if (toItem.ContainingProject != null) { if (!BuildPathFromCollection(toItem.ContainingProject.ProjectItems, toItem, ref path)) return ""; path = BuildPath(toItem.ContainingProject); path = path + Path.DirectorySeparatorChar + toItem.Name; } else { path = toItem.Name; } return path; } private static bool BuildPathFromCollection(ProjectItems items, ProjectItem target, ref string path) { if (items == null) return false; foreach (ProjectItem item in items) { if (item == target) { path = path + Path.DirectorySeparatorChar + target.Name; return true; } else { string tmp = path + Path.DirectorySeparatorChar + item.Name; ProjectItems childitems = item.ProjectItems; if (childitems == null && item.Object is Project) childitems = ((Project)item.Object).ProjectItems; bool found = BuildPathFromCollection(childitems, target, ref tmp); if (found) { path = tmp; return true; } } } return false; } /// <summary> /// Recursively tries to build a path from the parent project to the child one. /// Returns true if the path can be built. /// </summary> private static bool BuildPathToFolder(Project parent, Project target, ref string path) { if (parent == null) return false; foreach (ProjectItem item in parent.ProjectItems) { if (item.Object == target) { path = path + Path.DirectorySeparatorChar + target.Name; return true; } else if (item.Kind == Constants.vsProjectItemKindSolutionItems) { string tmp = path + Path.DirectorySeparatorChar + item.Name; bool found = BuildPathToFolder(item.Object as Project, target, ref tmp); if (found) { path = tmp; return true; } } } return false; } #endregion BuildPath #region Find methods /// <summary> /// Finds a project in the solution, given its output assembly name. /// </summary> /// <returns>A <see cref="Project"/> reference or <see langword="null" /> if /// it doesn't exist. Project can be C# or VB.</returns> public static Project FindProjectByAssemblyName(DTE vs, string name) { foreach (Project p in (Projects) vs.GetObject("CSharpProjects")) { if (p.Properties.Item("AssemblyName").Value.ToString() == name) return p; } foreach (Project p in (Projects) vs.GetObject("VBProjects")) { if (p.Properties.Item("AssemblyName").Value.ToString() == name) return p; } return null; } /// <summary> /// Finds a project in the solution, given its name. /// </summary> /// <returns>A <see cref="Project"/> reference or <see langword="null" /> if /// it doesn't exist. Project can be C# or VB.</returns> public static Project FindProjectByName(DTE vs, string name) { // Try the quick ones first. try { foreach (Project p in (Projects)vs.GetObject("CSharpProjects")) { if (p.Name == name) return p; } } catch { } // C# may not be installed. try { foreach (Project p in (Projects)vs.GetObject("VBProjects")) { if (p.Name == name) return p; } } catch { } // VB may not be installed. // We've no option but to iterate everything now. foreach (Project p in vs.Solution.Projects) { if (p.Name == name) { return p; } else if (p.ProjectItems != null) { Project inner = FindProjectByName(p.ProjectItems, name); if (inner != null) { return inner; } } } return null; } private static Project FindProjectByName(ProjectItems items, string name) { foreach (ProjectItem item in items) { if (item.Object is Project && ((Project)item.Object).Name == name) { return item.Object as Project; } else if (item.ProjectItems != null) { Project p = FindProjectByName(item.ProjectItems, name); if (p != null) { return p; } } } return null; } /// <summary> /// Finds a project item in the received collection, given its name. /// </summary> /// <param name="collection">The initial collection to start the search.</param> /// <param name="name">The name of the item to locate.</param> /// <param name="recursive">Specifies whether to search in items collections in turn.</param> /// <returns>A <see cref="Project"/> reference or <see langword="null" /> if /// it doesn't exist. Project can be C# or VB.</returns> public static ProjectItem FindItemByName(ProjectItems collection, string name, bool recursive) { foreach (ProjectItem item in collection) { if (item.Name == name) return item; // Recurse if specified. if (recursive) { ProjectItem child = FindItemByName(item.ProjectItems, name, recursive); if (child != null) return child; } } return null; } /// <summary> /// Finds a project item in the solution hierarchy, given its /// folder-like location path. /// </summary> /// <returns>The project item or <see langword="null" /> if /// it doesn't exist.</returns> public static ProjectItem FindItemByPath(Solution root, string path) { string[] allpaths = path.Split(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); // First path is the project/solution folder to look into. Project prj = null; foreach (Project p in root.Projects) { if (p.Name == allpaths[0]) { prj = p; break; } } if (prj == null) return null; string[] paths = new string[allpaths.Length - 1]; // If there are no child paths, this is not an item but the project itself. if (paths.Length == 0) return null; Array.Copy(allpaths, 1, paths, 0, paths.Length); return FindInCollectionRecursive(prj.ProjectItems, paths, 0); } private static ProjectItem FindInCollectionRecursive(ProjectItems collection, string[] paths, int index) { foreach (ProjectItem item in collection) { if (item.Name == paths[index]) { if (index == paths.Length - 1) { // We reached the item we were looking for. return item; } else { // Otherwise, keep processing. // If item is a project/solution folder, cast before moving on. if (item.Object is Project) { return FindInCollectionRecursive( ((Project)item.Object).ProjectItems, paths, ++index); } else { return FindInCollectionRecursive(item.ProjectItems, paths, ++index); } } } } // Item wasn't found. return null; } #endregion Find methods #region Get methods /// <summary> /// Retrieves the code file extension for the project. /// </summary> public static string GetDefaultExtension(Project project) { if (project.Kind == PrjKind.prjKindCSharpProject) return ".cs"; else if (project.Kind == PrjKind.prjKindVBProject) return ".vb"; else throw new NotSupportedException(String.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.DteHelper_UnsupportedProjectKind, project.Name)); } /// <summary> /// Retrieves a default namespace to use for project items. /// </summary> public static string GetProjectNamespace(Project project) { string ns = project.Properties.Item("DefaultNamespace").Value.ToString(); if (ns == null || ns == String.Empty) ns = project.Properties.Item("RootNamespace").Value.ToString(); if (ns == null || ns == String.Empty) ns = project.Properties.Item("AssemblyName").Value.ToString(); return ns; } /// <summary> /// Retrieves the project currently selected, if any. /// </summary> public static Project GetSelectedProject(DTE vs) { foreach (object obj in (object[]) vs.ActiveSolutionProjects) { if (obj is Project) return obj as Project; } return null; } /// <summary> /// Returns the item file name relative to the containing solution. /// </summary> public static string GetFilePathRelative(ProjectItem item) { return GetFilePathRelative(item.DTE, item.get_FileNames(1)); } /// <summary> /// Turns the file name received into a path relative to the containing solution. /// </summary> public static string GetFilePathRelative(DTE vs, string file) { if (!file.StartsWith(Path.GetDirectoryName(vs.Solution.FullName))) throw new ArgumentException(String.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.DteHelper_PathNotRelativeToSln, file, vs.Solution.FullName)); string relative = file.Replace(Path.GetDirectoryName(vs.Solution.FullName), ""); if (relative.StartsWith(Path.DirectorySeparatorChar.ToString())) relative = relative.Substring(1); return relative; } /// <summary> /// Turns the relative file name received into full path, based on the containing solution location. /// </summary> public static string GetPathFull(DTE vs, string file) { if (Path.IsPathRooted(file) && !file.StartsWith(Path.GetDirectoryName(vs.Solution.FullName))) throw new ArgumentException(String.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.DteHelper_PathNotRelativeToSln, file, vs.Solution.FullName)); return Path.Combine(Path.GetDirectoryName(vs.Solution.FullName), file); } #endregion Get methods #region Select methods /// <summary> /// Selects a project in the solution explorer. /// </summary> public static void SelectProject(Project project) { // Select the parent folder to add the project to it. Window win = project.DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer); win.Activate(); win.SetFocus(); UIHierarchy hier = win.Object as UIHierarchy; UIHierarchyItem sol = hier.UIHierarchyItems.Item(1); sol.Select(vsUISelectionType.vsUISelectionTypeSelect); // Remove project file name from path. string name = Path.GetDirectoryName(project.UniqueName); // Web projects can't be located through UniqueName. if (IsWebProject(project)) { // Locate by folder relative to solution one. // TODO: this will not work if project is NOT inside solution! name = Path.GetDirectoryName(project.Properties.Item("FullPath").Value.ToString()); string slnpath = Path.GetDirectoryName(project.DTE.Solution.FullName); name = name.Substring(name.IndexOf(slnpath) + slnpath.Length + 1); } // Perform selection. UIHierarchyItem item = null; try { item = hier.GetItem(Path.Combine(sol.Name, name)); } catch (ArgumentException) { // Retry selection by name (much slower!) item = FindProjectByName(project.Name, hier.UIHierarchyItems); } if (item != null) item.Select(vsUISelectionType.vsUISelectionTypeSelect); } private static UIHierarchyItem FindProjectByName(string name, UIHierarchyItems items) { foreach (UIHierarchyItem item in items) { if (item.Name == name) { ProjectItem pi = item.Object as ProjectItem; // Check the project name or the subproject name (for ETP). if (pi.ContainingProject.Name == name || (pi.SubProject != null && pi.SubProject.Name == name)) return item; } if (item.UIHierarchyItems != null) { UIHierarchyItem uii = FindProjectByName(name, item.UIHierarchyItems); if (uii != null) return uii; } } return null; } /// <summary> /// Selects a solution explorer item, based on /// its relative path with regards to the solution. /// </summary> public static UIHierarchyItem SelectItem(DTE vs, string path) { // Select the parent folder to add the project to it. Window win = vs.Windows.Item(Constants.vsWindowKindSolutionExplorer); win.Activate(); win.SetFocus(); UIHierarchy hier = win.Object as UIHierarchy; UIHierarchyItem sol = hier.UIHierarchyItems.Item(1); sol.Select(vsUISelectionType.vsUISelectionTypeSelect); // Perform selection. UIHierarchyItem item = FindHierarchyItemByPath(sol.UIHierarchyItems, path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar), 0); if (item != null) item.Select(vsUISelectionType.vsUISelectionTypeSelect); return item; } #region Find manually /// <summary> /// UIHierarchy.GetItem does not always work :S, so I do it by hand here. /// </summary> private static UIHierarchyItem FindHierarchyItemByPath(UIHierarchyItems items, string[] paths, int index) { foreach (UIHierarchyItem item in items) { if (item.Name == paths[index]) { if (index == paths.Length - 1) // We reached the item we were looking for. return item; else // Otherwise, keep processing. return FindHierarchyItemByPath(item.UIHierarchyItems, paths, ++index); } } // Item wasn't found. return null; } #endregion Find manually #endregion Select methods #region IsXXX methods /// <summary> /// Determines whether the project is a web project. /// </summary> public static bool IsWebProject(Project project) { // TODO: Is there a better way? return project.Properties.Item("WebServerVersion").Value != null && project.Properties.Item("WebServerVersion").Value.ToString() != String.Empty; } /// <summary> /// Determines whether the item is a child of the solution itself, /// that is, it's not contained in a project. Examples are the Solution Items folder /// and its items and Solution Folders. /// </summary> public static bool IsSolutionChild(SelectedItem item) { // Solution folders are exposed with the same kind as solution items. // This eases compatibility with VS2003 in the future. // It's either a direct folder or an item contained in one. if (item.ProjectItem != null) { return (item.ProjectItem.Object is Project && ((Project)item.ProjectItem.Object).Kind == Constants.vsProjectKindSolutionItems) || item.ProjectItem.ContainingProject == null || item.ProjectItem.ContainingProject.Kind == Constants.vsProjectKindSolutionItems; } else if (item.Project != null) { return (item.Project.Kind == Constants.vsProjectKindSolutionItems); } // All other cases go to the solution. return true; } #endregion IsXXX methods } } |