//------------------------------------------------------------------------------ // // Copyright (c) Company. All rights reserved. // //------------------------------------------------------------------------------ using System; using System.ComponentModel.Design; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using Microsoft.VisualStudio; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.Win32; using System.Collections.Specialized; using EnvDTE; using EnvDTE80; namespace SolutionOpen { /// /// This is the class that implements the package exposed by this assembly. /// /// /// /// The minimum requirement for a class to be considered a valid package for Visual Studio /// is to implement the IVsPackage interface and register itself with the shell. /// This package uses the helper classes defined inside the Managed Package Framework (MPF) /// to do it: it derives from the Package class that provides the implementation of the /// IVsPackage interface and uses the registration attributes defined in the framework to /// register itself and its components with the shell. These attributes tell the pkgdef creation /// utility what data to put into .pkgdef file. /// /// /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. /// /// [PackageRegistration(UseManagedResourcesOnly = true)] [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About [Guid(SolutionOpenPackage.PackageGuidString)] [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] [ProvideMenuResource("Menus.ctmenu", 1)] [ProvideAutoLoad(UIContextGuids80.SolutionExists)] public sealed class SolutionOpenPackage : Package { /// /// SolutionOpenPackage GUID string. /// public const string PackageGuidString = "e56d7fed-59bc-4323-b20f-17df4f10dbec"; /// /// Initializes a new instance of the class. /// public SolutionOpenPackage() { // Inside this method you can place any initialization code that does not require // any Visual Studio service because at this point the package object is created but // not sited yet inside Visual Studio environment. The place to do all the other // initialization is the Initialize method. } #region Package Members /// /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// protected override void Initialize() { base.Initialize(); outputWindowPane = ApplicationObject.ToolWindows.OutputWindow.OutputWindowPanes.Item("Build"); Events events = ApplicationObject.Events; buildEvents = events.BuildEvents; solutionEvents = events.SolutionEvents; projectItemEvents = events.MiscFilesEvents; buildEvents.OnBuildBegin += OnBuildBegin; buildEvents.OnBuildDone += OnBuildDone; solutionEvents.Opened += OnSolutionOpened; solutionEvents.AfterClosing += OnSolutionClosed; solutionEvents.ProjectAdded += OnProjectAdded; solutionEvents.ProjectRemoved += OnProjectRemoved; projectItemEvents.ItemAdded += OnProjectItemAdded; projectItemEvents.ItemRemoved += OnProjectItemRemoved; projectItemEvents.ItemRenamed += OnProjectItemRenamed; SolutionOpen.Command.SolutionOpen.Initialize(this); SolutionOpen.Command.HeaderFlip.Initialize(this); SolutionOpen.Command.RefreshFileList.Initialize(this); } #endregion #region Events private void OnBuildBegin(vsBuildScope buildScope, vsBuildAction buildAction) { startTime = DateTime.Now; } private void OnBuildDone(vsBuildScope buildScope, vsBuildAction buildAction) { DateTime now = DateTime.Now; TimeSpan timeSpan = now - this.startTime; this.outputWindowPane.OutputString(string.Format("Total build time: {0:00}s | {1:00}:{2:00}:{3:00}.{4:00}\n", new object[] { timeSpan.TotalSeconds, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds / 10 })); } private void OnSolutionOpened() { ClearAndRebuildPathList(); } private void OnSolutionClosed() { ClearAndRebuildPathList(); } private void OnProjectAdded(Project proj) { ClearAndRebuildPathList(); } private void OnProjectRemoved(Project proj) { ClearAndRebuildPathList(); } private void OnProjectItemAdded(ProjectItem item) { ClearAndRebuildPathList(); } private void OnProjectItemRemoved(ProjectItem item) { ClearAndRebuildPathList(); } private void OnProjectItemRenamed(ProjectItem item, string oldName) { ClearAndRebuildPathList(); } #endregion #region Members public static DTE2 ApplicationObject = GetGlobalService(typeof(DTE)) as DTE2; public static StringDictionary FilePaths = new StringDictionary(); private OutputWindowPane outputWindowPane; private BuildEvents buildEvents; private SolutionEvents solutionEvents; private ProjectItemsEvents projectItemEvents; private DateTime startTime; #endregion #region Methods public static string BaseName(string fullName) { int fileNameStart = fullName.LastIndexOfAny("\\/".ToCharArray()) + 1; int firstDot = fullName.IndexOf('.', fileNameStart); if (firstDot > 0) return fullName.Substring(fileNameStart, (firstDot - fileNameStart)); return fullName; } public static void FindFiles(ProjectItems projectItems, ref StringDictionary filePaths) { string[] validExtensions = new string[] { ".asm", ".c", ".cc", ".cfg", ".config", ".cp", ".cpp", ".cs", ".css", ".cxx", ".c++", ".def", ".h", ".hh", ".hpp", ".htm", ".html", ".h++", ".ini", ".inl", ".json", ".m", ".mm", ".py", ".res", ".resx", ".s", ".txt", ".vsct", ".vsixmanifest", }; foreach (ProjectItem projectItem in projectItems) { // check all the files in this project item for (int i = 0; i < projectItem.FileCount; ++i) { // Make sure the project item is a physical file if (projectItem.Kind == "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}") { string fileName = projectItem.get_FileNames(1); if (fileName != null) { string fileExt = Path.GetExtension(fileName).ToLower(); if (Array.IndexOf(validExtensions, fileExt) != -1) filePaths[fileName] = fileName; } } } // recurse into any project items within this project item if (projectItem.ProjectItems != null) FindFiles(projectItem.ProjectItems, ref filePaths); // handle sub-projects if (projectItem.SubProject != null) FindFiles(projectItem.SubProject.ProjectItems, ref filePaths); } } public static void ClearAndRebuildPathList() { FilePaths.Clear(); Projects projects = ApplicationObject.Solution.Projects; for (int i = 1; i <= projects.Count; ++i) FindFiles(projects.Item(i).ProjectItems, ref FilePaths); } #endregion } }