//------------------------------------------------------------------------------
//
// 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
}
}