A simple Visual Studio extension that shows the solution full path next to VS window title.
To achieve that i create a visual studio extension package that needs to load as soon as a solution is detected. Then, i hook to solution opened and renamed events. On both events i read solution’s full path and append window’s title.
Package/Extension entry point:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[PackageRegistration(UseManagedResourcesOnly = true)] [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About [Guid(MainPackage.PackageGuidString)] [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] [ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)] public sealed class MainPackage : Package { //... protected override void Initialize() { base.Initialize(); var dte = this.GetService(typeof(DTE)) as DTE; var solution = this.GetService(typeof(SVsSolution)) as IVsSolution; var packageMnager = new PackageManager(dte, solution); packageMnager.Initialise(); } } |
The actual work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
public class PackageManager { private readonly IVsSolution solution; private readonly DTE dte; private string defaultTitle; private uint handleCookie = uint.MaxValue; public PackageManager(DTE dte, IVsSolution solution) { this.dte = dte; this.solution = solution; } public void Initialise() { this.PreserveDefaultTitle(); var proxy = new SolutionEventsProxy(); this.solution?.AdviseSolutionEvents(proxy, out handleCookie); proxy.AfterSolutionOpened += OnAfterSolutionOpened; this.dte.Events.SolutionEvents.Renamed += SolutionEventsOnRenamed; } private void OnAfterSolutionOpened(object sender, EventArgs eventArgs) { this.UpdateTitle(); } private void SolutionEventsOnRenamed(string oldName) { this.UpdateTitle(); } private void UpdateTitle() { var info = ReadSolutionPath(); SetWindowTitle(FormatTitleText(info)); } private string ReadSolutionPath() { string pbstrSolutionDirectory, pbstrSolutionFile, pbstrUserOptsFile; this.solution.GetSolutionInfo(out pbstrSolutionDirectory, out pbstrSolutionFile, out pbstrUserOptsFile); return pbstrSolutionDirectory; } private static string GetWindowTitle() { return Application.Current.MainWindow.Title; //Access WPF window control } private static void SetWindowTitle(string text) { Action action = () => Application.Current.MainWindow.Title = text; var dispatcher = Application.Current.Dispatcher; dispatcher?.BeginInvoke(action); } //... } |
Hooking to solution events:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class SolutionEventsProxy : IVsSolutionEvents3 { public event EventHandler AfterSolutionOpened; #region IVsSolutionEvents3 public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) { return VSConstants.S_OK; } public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) { AfterSolutionOpened?.Invoke(this, EventArgs.Empty); return VSConstants.S_OK; } //Rest of IVsSolutionEvents3 implementation //... #endregion } |
To install the extension click here.