For a small community discussion, what are some essential Visual Studio macros you use?
I just started learning about them, and want to hear what some of you can't live without.
I add buttons on the toolbar for the following 3 macros. Each will take the currently selected text in any file and google it (or MSDN-it, or spell-check-it). Make up a nifty icon for the toolbar for extra style-points.
Private Const BROWSER_PATH As String = "C:\Program Files\Mozilla Firefox\firefox.exe" Sub SearchGoogle() Dim cmd As String cmd = String.Format("{0} http://www.google.com/search?hl-en&q={1}", BROWSER_PATH, DTE.ActiveDocument.Selection.Text) Shell(cmd, AppWinStyle.NormalFocus) End Sub Sub SearchMSDN() Dim cmd As String cmd = String.Format("{0} http://www.google.com/search?hl-en&q={1}+site%3Amsdn.microsoft.com", BROWSER_PATH, DTE.ActiveDocument.Selection.Text) Shell(cmd, AppWinStyle.NormalFocus) End Sub Sub SpellCheck() Dim cmd As String cmd = String.Format("{0} http://www.spellcheck.net/cgi-bin/spell.exe?action=CHECKWORD&string={1}", BROWSER_PATH, DTE.ActiveDocument.Selection.Text) Shell(cmd, AppWinStyle.NormalFocus) End Sub Show build duration in the Output window
Put this code in your EnvironmentEvents module. This will write the duration directly to the build window for any action on a solution (build, rebuild, clean, deploy).
You can change the IsBuild function to specify the actions you want to see this information for.
Dim buildStart As Date Private Function IsBuild(ByVal scope As EnvDTE.vsBuildScope, ByVal action As EnvDTE.vsBuildAction) As Boolean Return scope = vsBuildScope.vsBuildScopeSolution End Function Private Sub BuildEvents_OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildBegin If (IsBuild(Scope, Action)) Then buildStart = Date.Now End If End Sub Private Sub BuildEvents_OnBuildDone(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildDone If (IsBuild(Scope, Action)) Then Dim buildTime = Date.Now - buildStart WriteToBuildWindow(String.Format("Build time: {0}", buildTime.ToString)) End If End Sub Private Sub WriteToBuildWindow(ByVal message As String) Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput) Dim ow As OutputWindow = CType(win.Object, OutputWindow) For Each owPane As OutputWindowPane In ow.OutputWindowPanes If (owPane.Name.Equals("Build")) Then owPane.OutputString(message) Exit For End If Next End Sub ow.OutputWindowPanes.Item("Build").OutputString(message) instead of the For Each.Show the start page after you close a solution (but keep Visual Studio open)
Put this code in your EnvironmentEvents module:
Private Sub SolutionEvents_AfterClosing() Handles SolutionEvents.AfterClosing DTE.ExecuteCommand("View.StartPage") End Sub Hide the start page after you open a solution
Put this code in your EnvironmentEvents module:
Private Sub SolutionEvents_Opened() Handles SolutionEvents.Opened Dim startPageGuid As String = "{387CB18D-6153-4156-9257-9AC3F9207BBE}" Dim startPage As EnvDTE.Window = DTE.Windows.Item(startPageGuid) If startPage IsNot Nothing Then startPage.Close() End Sub
These two together will cause your Start Page to hide itself when you open a solution. When you close the solution, the Start Page comes back.
I use the following lesser-known shortcuts very often:
Outlining: Collapse to definitions but expand regions
Are you working in one of those shops that insists on regions around everything, so that when you collapse to definitions, you can't see any code?
What you really need is a collapse-to-definitions-but-expand-regions macro, like this one:
Sub CollapseToDefinitionsButExpandAllRegions() DTE.ExecuteCommand("Edit.CollapsetoDefinitions") DTE.SuppressUI = True Dim objSelection As TextSelection = DTE.ActiveDocument.Selection objSelection.StartOfDocument() Do While objSelection.FindText("#region", vsFindOptions.vsFindOptionsMatchInHiddenText) Loop objSelection.StartOfDocument() DTE.SuppressUI = False End Sub Put this in a regular macro module, assign it to a hot key, and your code is back.
(Except...if you work with some really nefarious individuals who put regions inside methods, this will unfortunately expand those methods. If anybody knows a way to write this to avoid that, feel free to edit.)
Insert GUID, great for WiX work, add to menu as button or as key shortcut.
Sub InsertGuid() Dim objTextSelection As TextSelection objTextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection) objTextSelection.Text = System.Guid.NewGuid.ToString.ToUpper(New System.Globalization.CultureInfo("en", False)) End Sub Organise usings for all .cs files in a solution - Original Author: djpark.
Sub OrganizeSolution() Dim sol As Solution = DTE.Solution For i As Integer = 1 To sol.Projects.Count OrganizeProject(sol.Projects.Item(i)) Next End Sub Private Sub OrganizeProject(ByVal proj As Project) For i As Integer = 1 To proj.ProjectItems.Count OrganizeProjectItem(proj.ProjectItems.Item(i)) Next End Sub Private Sub OrganizeProjectItem(ByVal projectItem As ProjectItem) Dim fileIsOpen As Boolean = False If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then 'If this is a c# file If projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 Then 'Set flag to true if file is already open fileIsOpen = projectItem.IsOpen Dim window As Window = projectItem.Open(Constants.vsViewKindCode) window.Activate() projectItem.Document.DTE.ExecuteCommand("Edit.RemoveAndSort") 'Only close the file if it was not already open If Not fileIsOpen Then window.Close(vsSaveChanges.vsSaveChangesYes) End If End If End If 'Be sure to apply RemoveAndSort on all of the ProjectItems. If Not projectItem.ProjectItems Is Nothing Then For i As Integer = 1 To projectItem.ProjectItems.Count OrganizeProjectItem(projectItem.ProjectItems.Item(i)) Next End If 'Apply RemoveAndSort on a SubProject if it exists. If Not projectItem.SubProject Is Nothing Then OrganizeProject(projectItem.SubProject) End If End Sub Collapse all nodes of the Solution panel, very useful especially for big projects:
Public Module CollapseAllNodes Sub RunCollapseAllNodes() Dim UIHSolutionExplorer As UIHierarchy UIHSolutionExplorer = DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Object() ' Check if there is any open solution If (UIHSolutionExplorer.UIHierarchyItems.Count = 0) Then Return End If ' Get the top node (the name of the solution) Dim UIHSolutionRootNode As UIHierarchyItem UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1) CloseRecursif(UIHSolutionRootNode) ' Select the solution node, or else when you click ' on the solution windows scrollbar, it will synchronize the open document ' with the tree and pop out the corresponding node which is probably not ' what you want. UIHSolutionRootNode.Select(vsUISelectionType.vsUISelectionTypeSelect) End Sub Function CloseRecursif(ByRef element) For Each UIHChild In element.UIHierarchyItems() CloseRecursif(UIHChild) If (UIHChild.UIHierarchyItems.Expanded = True) Then UIHChild.UIHierarchyItems.Expanded = False End If Next End Function End Module I use Jeff's FormatToHtml macros if I'm going to be pasting a code example into a blog post or an email.
I work with dual monitors, and I find Sharon's layout-switching macro (from a 1 monitor to a 2 monitor layout) totally invaluable. When you need to be referencing a web page or other program while typing a bit of code, Ctrl-Alt-1 to switch to a one monitor layout for your Visual Studio windows. Once you're done, Ctrl-Alt-2 to switch to your two monitor layout and get all your windows back. Awesome!
http://www.invisible-city.com/sharon/2008/06/workstation-hack-visual-studio-on-2.html
Not a macro on its own, but useful:
Public Sub WriteToOutputWindow(ByVal pane as String, ByVal Msg As String) Dim owPane As OutputWindowPane Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput) Dim ow As OutputWindow = win.Object Try owPane = ow.OutputWindowPanes.Item(pane) Catch owPane = ow.OutputWindowPanes.Add(pane) End Try If Not owPane Is Nothing Then owPane.Activate() owPane.OutputString(Msg & vbCrLf) End If End Sub I'm currently working on two different projects with different coding standards, one that uses tabs for line beginnings and another that uses spaces. This macro will toggle between which standard is used based on which environment is currently active:
Public Sub ToggleTabs() If DTE.ActiveDocument.Language = "CSharp" Then Dim currentSetting As Boolean = DTE.Properties("TextEditor", "CSharp").Item("InsertTabs").Value DTE.Properties("TextEditor", "CSharp").Item("InsertTabs").Value = Not currentSetting End If If DTE.ActiveDocument.Language = "SQL" Then Dim currentSQLSetting As Boolean = DTE.Properties("TextEditor", "SQL").Item("InsertTabs").Value DTE.Properties("TextEditor", "SQL").Item("InsertTabs").Value = Not currentSQLSetting End If If DTE.ActiveDocument.Language = "HTML" Then Dim currentHTMLSetting As Boolean = DTE.Properties("TextEditor", "HTML").Item("InsertTabs").Value DTE.Properties("TextEditor", "HTML").Item("InsertTabs").Value = Not currentHTMLSetting End If If DTE.ActiveDocument.Language = "JScript" Then Dim currentJScriptSetting As Boolean = DTE.Properties("TextEditor", "JScript").Item("InsertTabs").Value DTE.Properties("TextEditor", "JScript").Item("InsertTabs").Value = Not currentJScriptSetting End If End Sub I used to employ a lot of macros in VS 2002/2003. One example would be Region creation - I always like my classes to be divided into the following regions - "Private members", "Public Properties", "Public Methods" and "Private methods". So, I have a macro mapped to a shortcut key that creates these regions in any new class file.
Refactoring support in VS 2005/2008 (and the facility of adding common code snippets) as well as the use of Addins like DXCore and SlickEdit allow me to work without having to create too many macros anymore.
I couldn't let this question go without mentioning this one. It even has a video to show how to install and use it. This macro simply allows you to create the nested files in the solution explorer (like resources.resx).
Edit: Updated the link
My Documents\Visual Studio 2012\Addins. There, for your projectwhatever, put thewhatever.dllfor your add-in, as well as thewhatever.AddInfile from the main project directory.