Home Professional Edition Commands Extensions SSMS Resources What's New

Visual Commander Visual Commander

Extensions

An extension can subscribe to Visual Studio IDE events in the SetSite method and must unsubscribe from them in the Close method.

1. Display document path of the active window in the status bar.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		events = DTE.Events;
		windowEvents = events.WindowEvents;
		windowEvents.WindowActivated += OnWindowActivated;
		System.IServiceProvider serviceProvider = package as System.IServiceProvider;
		statusBar = serviceProvider.GetService(
			typeof(Microsoft.VisualStudio.Shell.Interop.SVsStatusbar)) as 
				Microsoft.VisualStudio.Shell.Interop.IVsStatusbar;
	}
	public void Close()
	{
		windowEvents.WindowActivated -= OnWindowActivated;
	}
	private void OnWindowActivated(EnvDTE.Window gotFocus, EnvDTE.Window lostFocus)
	{
		try
		{
			if (gotFocus.Document != null)
				Show(gotFocus.Document.FullName);
			else
				Show(gotFocus.Caption);
		}
		catch (System.Exception e)
		{
		}
	}
	private void Show(string s)
	{
		int frozen;
		statusBar.IsFrozen(out frozen);
		if (frozen == 0)
			statusBar.SetText(s);
	}
	private EnvDTE.Events events;
	private EnvDTE.WindowEvents windowEvents;
	private Microsoft.VisualStudio.Shell.Interop.IVsStatusbar statusBar;
}

2. Run Cppcheck on the saved file and show results in the Output window.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE_, Microsoft.VisualStudio.Shell.Package package)
	{
		DTE = DTE_;
		events = DTE.Events;
		documentEvents = events.DocumentEvents;
		documentEvents.DocumentSaved += OnDocumentSaved;
	}
	public void Close()
	{
		documentEvents.DocumentSaved -= OnDocumentSaved;
	}
	private void OnDocumentSaved(EnvDTE.Document doc)
	{
		if(doc.Language == "C/C++")
			RunCppcheck(doc.FullName);
	}
	private void RunCppcheck(string file)
	{
		GetOutputPane().Clear();
		System.Diagnostics.Process p = new System.Diagnostics.Process();
		p.StartInfo.FileName = @"C:\Program Files (x86)\Cppcheck\cppcheck.exe";
		p.StartInfo.Arguments = "--quiet --verbose --template=vs \"" + file + "\"";
		p.StartInfo.UseShellExecute = false;
		p.StartInfo.CreateNoWindow = true;
		p.StartInfo.RedirectStandardOutput = true;
		p.StartInfo.RedirectStandardInput = true;
		p.StartInfo.RedirectStandardError = true;
		p.OutputDataReceived  += (sender, args) => OutputString(args.Data);
		p.ErrorDataReceived  += (sender, args) => OutputString(args.Data);
		p.Start();
		p.BeginOutputReadLine();
		p.BeginErrorReadLine();
		p.WaitForExit();
		p.Close();
	}
	private void OutputString(string line)
	{
		GetOutputPane().OutputString(line + System.Environment.NewLine);
	}
	private EnvDTE.OutputWindowPane GetOutputPane()
	{
		string cppcheckPaneName = "Cppcheck"; 
		foreach (EnvDTE.OutputWindowPane pane in 
			DTE.ToolWindows.OutputWindow.OutputWindowPanes)
		{
			if (pane.Name == cppcheckPaneName)
				return pane;
		}
		return DTE.ToolWindows.OutputWindow.OutputWindowPanes.Add(cppcheckPaneName);
	}
	private EnvDTE80.DTE2 DTE;
	private EnvDTE.Events events;
	private EnvDTE.DocumentEvents documentEvents;
}

3. Hide Sign in and Feedback buttons.

Download vcmd

C#

References: System.Xaml

public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		timer = new System.Windows.Threading.DispatcherTimer();
		timer.Interval = System.TimeSpan.FromMilliseconds(1000);
		timer.Tick += OnTimer;
		timer.Start();
	}
	public void Close()
	{
		timer.Stop();
	}
	private void OnTimer(System.Object o, System.EventArgs a)
	{
		try
		{
			if (HideSignIn() && HideFeedback())
				;
		}
		catch (System.Exception e)
		{
		}
	}
	private bool HideSignIn()
	{
		System.Windows.FrameworkElement e = 
			FindElement(System.Windows.Application.Current.MainWindow, 
				"PART_MenuBarFrameControlContainer");
		if (e != null)
		{
			e.Visibility = System.Windows.Visibility.Collapsed;
			return true;
		}
		return false;
	}
	private bool HideFeedback()
	{	
		System.Windows.FrameworkElement e = 
			FindElement(System.Windows.Application.Current.MainWindow, 
				"PART_TitleBarFrameControlContainer");
		if (e != null)
		{
			System.Windows.DependencyObject o1 = 
				System.Windows.Media.VisualTreeHelper.GetChild(e, 0);
			System.Windows.DependencyObject o2 = 
				System.Windows.Media.VisualTreeHelper.GetChild(o1, 0);
			System.Windows.DependencyObject o3 = 
				System.Windows.Media.VisualTreeHelper.GetChild(o2, 0);
			if (System.Windows.Media.VisualTreeHelper.GetChildrenCount(o3) == 3)
			{
				System.Windows.DependencyObject o4 = 
					System.Windows.Media.VisualTreeHelper.GetChild(o3, 1);
				(o4 as System.Windows.FrameworkElement).Visibility = 
					System.Windows.Visibility.Collapsed;
				return true;
			}
		}
		return false;
	}
	private System.Windows.FrameworkElement FindElement(System.Windows.Media.Visual v, string name)
	{
		if (v == null)
			return null;
		for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(v); ++i)
		{
			System.Windows.Media.Visual child = 
				System.Windows.Media.VisualTreeHelper.GetChild(v, i) as
					System.Windows.Media.Visual;
			if (child != null)
			{
				System.Windows.FrameworkElement e = 
					child as System.Windows.FrameworkElement;
				if (e != null && e.Name == name)
					return e;
			}
			System.Windows.FrameworkElement result = FindElement(child, name);
			if (result != null)
				return result;
		}
		return null;
	}
	private System.Windows.Threading.DispatcherTimer timer;
}

4. Hide title bar in Visual Studio 2013.

Download vcmd

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		events = DTE.Events;
		dteEvents = events.DTEEvents;
		dteEvents.OnStartupComplete += OnStartupComplete;
	}
	public void Close()
	{
		dteEvents.OnStartupComplete -= OnStartupComplete;
	}
	private void OnStartupComplete()
	{
		try
		{
			HideTitleBar();
		}
		catch
		{
		}
	}
	private bool HideTitleBar()
	{
		System.Windows.FrameworkElement e = 
			FindElement(System.Windows.Application.Current.MainWindow, 
				"MainWindowTitleBar");
		if (e != null)
		{
			e.Visibility = System.Windows.Visibility.Collapsed;
			return true;
		}
		return false;
	}
	private System.Windows.FrameworkElement FindElement(System.Windows.Media.Visual v, string name)
	{
		if (v == null)
			return null;
		for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(v); ++i)
		{
			System.Windows.Media.Visual child = 
				System.Windows.Media.VisualTreeHelper.GetChild(v, i) as
					System.Windows.Media.Visual;
			if (child != null)
			{
				System.Windows.FrameworkElement e = 
					child as System.Windows.FrameworkElement;
				if (e != null && e.Name == name)
					return e;
			}
			System.Windows.FrameworkElement result = FindElement(child, name);
			if (result != null)
				return result;
		}
		return null;
	}
	private EnvDTE.Events events;
	private EnvDTE.DTEEvents dteEvents;
}

5. Minimize Visual Studio on Debugging.

Download vcmd

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE_, Microsoft.VisualStudio.Shell.Package package)
	{
		DTE = DTE_;
		events = DTE.Events;
		debuggerEvents = events.DebuggerEvents;
		debuggerEvents.OnEnterRunMode += OnEnterRunMode;
	}
	public void Close()
	{
		debuggerEvents.OnEnterRunMode -= OnEnterRunMode;
	}
	private void OnEnterRunMode(EnvDTE.dbgEventReason reason)
	{
		try
		{
			if (reason == EnvDTE.dbgEventReason.dbgEventReasonGo)
				DTE.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMinimize;
		}
		catch
		{
		}
	}
	EnvDTE80.DTE2 DTE;
	private EnvDTE.Events events;
	private EnvDTE.DebuggerEvents debuggerEvents;
}

6. Report warning if missing files on build.

Download vcmd

VB
Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.VisualStudio.Shell
Public Class E
	Implements VisualCommanderExt.IExtension
	Sub SetSite(DTE_ As DTE2, package As Package) Implements VisualCommanderExt.IExtension.SetSite
		DTE = DTE_
		events = DTE.Events
		buildEvents = events.BuildEvents
		AddHandler buildEvents.OnBuildBegin, AddressOf OnBuildBegin
	End Sub
	Sub Close() Implements VisualCommanderExt.IExtension.Close
		RemoveHandler buildEvents.OnBuildBegin, AddressOf OnBuildBegin
	End Sub
	Private Sub OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As vsBuildAction)
		For Each proj As Project In DTE.Solution.Projects
			For Each item As ProjectItem In proj.ProjectItems
				If (item.Kind <> "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}") Then 
					Continue For
				End If
				For i As Integer = 1 To item.FileCount
					Dim path As String = item.FileNames(i)
					If Not System.IO.File.Exists(item.FileNames(i)) Then
						WriteToBuildWindow(
							"!! Missing file:" & item.FileNames(i) + 
							" in project " + proj.Name)
					End If
				Next
			Next
		Next
	End Sub
	Private Sub WriteToBuildWindow(ByVal text As String)
		Dim ow As OutputWindow = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).Object
		Dim build As OutputWindowPane = ow.OutputWindowPanes.Item("Build")
		build.OutputString(text & System.Environment.NewLine)
	End Sub
	private DTE As EnvDTE80.DTE2
	private events As EnvDTE.Events
	private buildEvents as EnvDTE.BuildEvents
End Class
(Original macro code is here by Simon Mourier.)

7. Make Output show Build Order by default.

VB
Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.VisualStudio.Shell
Public Class E
	Implements VisualCommanderExt.IExtension
	Sub SetSite(DTE_ As DTE2, package As Package) Implements VisualCommanderExt.IExtension.SetSite
		DTE = DTE_
		events = DTE.Events
		buildEvents = events.BuildEvents
		AddHandler buildEvents.OnBuildBegin, AddressOf OnBuildBegin
	End Sub
	Sub Close() Implements VisualCommanderExt.IExtension.Close
		RemoveHandler buildEvents.OnBuildBegin, AddressOf OnBuildBegin
	End Sub
	Private Sub OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As vsBuildAction)
		Dim window As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput) 
		Dim output As OutputWindow = CType(window.Object, OutputWindow)
		For Each pane As OutputWindowPane In output.OutputWindowPanes 
			If (pane.Guid = "{2032B126-7C8D-48AD-8026-0E0348004FC0}") Then 
				pane.Activate()
			End If
		Next
		window.Activate()
	End Sub
	private DTE As EnvDTE80.DTE2
	private events As EnvDTE.Events
	private buildEvents as EnvDTE.BuildEvents
End Class
(Original macro code is here by Simon Mourier.)

8. Prevent Visual Studio from remembering last opened files.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE_, Microsoft.VisualStudio.Shell.Package package)
	{
		DTE = DTE_;
		events = DTE.Events;
		solutionEvents = events.SolutionEvents;
		solutionEvents.BeforeClosing += OnSolutionBeforeClosing;
	}
	public void Close()
	{
		solutionEvents.BeforeClosing -= OnSolutionBeforeClosing;
	}
	private void OnSolutionBeforeClosing()
	{
		try
		{
			DTE.ExecuteCommand("Window.CloseAllDocuments");
		}
		catch (System.Exception e)
		{
		}
	}
	EnvDTE80.DTE2 DTE;
	private EnvDTE.Events events;
	private EnvDTE.SolutionEvents solutionEvents;
}

9. Open a file from the solution directory on opening a solution.

C#
public class E : VisualCommanderExt.IExtension
{
    public void SetSite(EnvDTE80.DTE2 DTE_, Microsoft.VisualStudio.Shell.Package package)
    {
        DTE = DTE_;
        events = DTE.Events;
        solutionEvents = events.SolutionEvents;
        solutionEvents.Opened += OnSolutionOpened;
    }
    public void Close()
    {
        solutionEvents.Opened -= OnSolutionOpened;
    }
    private void OnSolutionOpened()
    {
        try
        {
            string startupFile = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(DTE.Solution.FullName), "startup.html");
            if(System.IO.File.Exists(startupFile))
                DTE.ItemOperations.OpenFile(startupFile);
        }
        catch (System.Exception e)
        {
        }
    }
    EnvDTE80.DTE2 DTE;
    private EnvDTE.Events events;
    private EnvDTE.SolutionEvents solutionEvents;
}

10. AutoSave files when Visual Studio loses focus.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE_, Microsoft.VisualStudio.Shell.Package package)
	{
		DTE = DTE_;
		System.Windows.Application.Current.Deactivated += OnDeactivated;
	}
	public void Close()
	{
		System.Windows.Application.Current.Deactivated -= OnDeactivated;
	}
	private void OnDeactivated(object sender, System.EventArgs e)
	{
		try
		{
			DTE.ExecuteCommand("File.SaveAll");
		}
		catch (System.Exception ex)
		{
		}
	}
	private EnvDTE80.DTE2 DTE;
}

11. Add version overlay to the Visual Studio 2015 taskbar icon.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		if (DTE.Version.Substring(0, 2) == "14") // VS 2015
			AddOverlay("15", System.Windows.Media.Brushes.Lime);
	}
	public void Close()
	{
	}
    private void AddOverlay(string text, System.Windows.Media.Brush color)
    {
        System.Windows.Media.FormattedText formattedText = new System.Windows.Media.FormattedText(text, 
            System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, 
            new System.Windows.Media.Typeface("Arial"), 12, color);
        System.Windows.Media.Drawing drawing = new System.Windows.Media.GeometryDrawing(color,
            new System.Windows.Media.Pen(color, 1),
            formattedText.BuildGeometry(new System.Windows.Point(0, 0)));
        System.Windows.Shell.TaskbarItemInfo taskbarItem = new System.Windows.Shell.TaskbarItemInfo();
        taskbarItem.Overlay = new System.Windows.Media.DrawingImage(drawing);
        System.Windows.Application.Current.MainWindow.TaskbarItemInfo = taskbarItem;
    }
}
Version icon overlay

12. Set original Visual Studio 2015 RTM icon for the Visual Studio 2015 Update 1 taskbar icon.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		vs2015 = DTE.Version.Substring(0, 2) == "14";
		if (vs2015)
		{
			events = DTE.Events;
			dteEvents = events.DTEEvents;
			dteEvents.OnStartupComplete += OnStartupComplete;
			timer = new System.Windows.Threading.DispatcherTimer();
			timer.Interval = System.TimeSpan.FromMilliseconds(10);
			timer.Tick += OnTimer;
		}
	}
	public void Close()
	{
		if (vs2015)
		{
			dteEvents.OnStartupComplete -= OnStartupComplete;
			timer.Stop();
		}
	}
	private void OnStartupComplete()
	{
		try
		{
			timer.Start();
		}
		catch
		{
		}
	}
	private void OnTimer(System.Object o, System.EventArgs a)
	{
		try
		{
			timer.Stop();
			string localFile = System.IO.Path.Combine(
				System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), // %AppData%
				@"VS2015RTM.ico");
			SetIcon(System.IO.File.Exists(localFile) ? localFile : @"https://vlasovstudio.com/etc/VS2015RTM.ico");
		}
		catch (System.Exception e)
		{
		}
	}
	private void SetIcon(string file)
	{
		System.Windows.Application.Current.MainWindow.Icon = 
			new System.Windows.Media.Imaging.BitmapImage(new System.Uri(file));
	}
	bool vs2015;
	private EnvDTE.Events events;
	private EnvDTE.DTEEvents dteEvents;
	private System.Windows.Threading.DispatcherTimer timer;
}
VS 2015 RTM icon for VS 2015 Update 1

13. Monitor commands execution.

C#
public class E : VisualCommanderExt.IExtension
{
    public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
    {
        events = DTE.Events;
        commandEvents = events.get_CommandEvents(null, 0);
        commands = DTE.Commands as EnvDTE80.Commands2;
        commandEvents.BeforeExecute += OnBeforeExecute;
        commandEvents.AfterExecute += OnAfterExecute;
    }
    public void Close()
    {
        commandEvents.BeforeExecute -= OnBeforeExecute;
        commandEvents.AfterExecute -= OnAfterExecute;
    }
    private void OnBeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
    {
        string name = GetCommandName(Guid, ID);
        if (name == "Debug.Start")
            System.Windows.MessageBox.Show("OnBeforeExecute Debug.Start");
    }
    private void OnAfterExecute(string Guid, int ID, object CustomIn, object CustomOut)
    {
        string name = GetCommandName(Guid, ID);
        if (name == "Debug.Start")
            System.Windows.MessageBox.Show("OnAfterExecute Debug.Start");
    }
    private string GetCommandName(string Guid, int ID)
    {
        if (Guid == null)
            return "null";
        try
        {
            return commands.Item(Guid, ID).Name;
        }
        catch (System.Exception)
        {
        }
        return "";
    }
    private EnvDTE.Events events;
    private EnvDTE.CommandEvents commandEvents;
    private EnvDTE80.Commands2 commands;
}

15. Hide the Publish button in the status bar of Visual Studio 2015 Update 2.

C#
public class E : VisualCommanderExt.IExtension
{
	public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
	{
		timer = new System.Windows.Threading.DispatcherTimer();
		timer.Interval = System.TimeSpan.FromMilliseconds(1000);
		timer.Tick += OnTimer;
		timer.Start();
	}
	 
	public void Close()
	{
		timer.Stop();
	}
		 
	private void OnTimer(System.Object o, System.EventArgs a)
	{
		try
		{
			if (HidePublish())
				timer.Stop();
		}
		catch (System.Exception e)
		{
		}
	}
		 
	private bool HidePublish()
	{
		System.Windows.FrameworkElement e = 
			FindElement(System.Windows.Application.Current.MainWindow, 
				"PublishCompartment");
		if (e != null)
		{
			e.Visibility = System.Windows.Visibility.Collapsed;
			return true;
		}
		return false;
	}
		 
	private System.Windows.FrameworkElement FindElement(System.Windows.Media.Visual v, string name)
	{
		if (v == null)
			return null;
		for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(v); ++i)
		{
			System.Windows.Media.Visual child = 
				System.Windows.Media.VisualTreeHelper.GetChild(v, i) as
					System.Windows.Media.Visual;
			if (child != null)
			{
				System.Windows.FrameworkElement e = 
					child as System.Windows.FrameworkElement;
				if (e != null && e.Name == name)
					return e;
			}
			System.Windows.FrameworkElement result = FindElement(child, name);
			if (result != null)
				return result;
		}
		return null;
	}
		 
	private System.Windows.Threading.DispatcherTimer timer;
}

16. Code indent helper for C++ macros in Unreal Engine 4.

UE4 Smarter Macro Indenting by hackalyze.

17. Add confirmation before running Build.RebuildSolution and other rebuild commands.

C#
public class E : VisualCommanderExt.IExtension
{
    public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
    {
        events = DTE.Events;
        commandEvents = events.get_CommandEvents(null, 0);
        commands = DTE.Commands as EnvDTE80.Commands2;
        commandEvents.BeforeExecute += OnBeforeExecute;
    }

    public void Close()
    {
        commandEvents.BeforeExecute -= OnBeforeExecute;
    }

    private void OnBeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
    {
        string name = GetCommandName(Guid, ID);
        if (name.Contains("Rebuild"))
        {
            if (System.Windows.MessageBox.Show("Are you sure you want to Rebuild?", "Confirm", 
                System.Windows.MessageBoxButton.YesNo) != System.Windows.MessageBoxResult.Yes)
            {
                CancelDefault = true;
            }
        }
    }

    private string GetCommandName(string Guid, int ID)
    {
        if (Guid == null)
            return "null";
        try
        {
            return commands.Item(Guid, ID).Name;
        }
        catch (System.Exception)
        {
        }
        return "";
    }

    private EnvDTE.Events events;
    private EnvDTE.CommandEvents commandEvents;
    private EnvDTE80.Commands2 commands;
}