Jay Harris is Cpt. LoadTest

a .net developers blog on improving user experience of humans and coders
Home | About | Speaking | Contact | Archives | RSS
 
Filed under: Speaking | Tools | Visual Studio

Increasing or decreasing the font size of your code in Visual Studio's text editor is almost required whenever VS is fired up on a projector. Anyone who has had to demo code, or give a talk at a user group, or present new technologies to their team has experienced the pain of increasing the font size through the Tools -> Options menu, followed by an inquiry to the crowd: "How's that? Is this font size readable by everyone?" Often times the selected size is not quite the right solution, and the process is repeated. Life as a presenter would be easier if only you could modify the font size through a simple keyboard command, similar to how browsers enable you adjust the font through the ctrl+ and ctrl- commands.

Macros.Samples.Accessibility.DecreaseTextEditorFontSize
Decreases the text editor font size in Visual Studio

Macros.Samples.Accessibility.IncreaseTextEditorFontSize
Increases the text editor font size in Visual Studio

Fortunately, this is easy with the help of Visual Studio's Sample Macros. To help show you the ropes of writing custom macros, VS ships with a collection samples, and two of these samples respectively increase and decrease the font size of the text editor. Right out of the box, Visual Studio comes with the ability to modify the font size for your code; all that remains is mapping these macros to the keyboard.

Visual Studio Options Window, Assigning Macro to Keyboard CommandMapping to the Keyboard

Anchoring these macros to specific keyboard commands is a simple process.

  1. From Visual Studio, access the Tools -> Options menu.
  2. In the Options window, navigate to Environment -> Keyboard.
  3. Using the "Show commands containing" input, enter in IncreaseText or DecreaseText. The list of available commands will automatically filter as you type, reducing the list to the applicable macro.
  4. Select the macro command, and select the "Press shortcut keys" input, and enter your desired keyboard command. Click the Assign button to set the command. I use "Ctrl, Alt, Shift, =" (plus) and "Ctrl, Alt, Shift, -" for my Increase and Decrease commands, respectively.
Monday, 26 January 2009 11:38:48 (Eastern Standard Time, UTC-05:00)  #    Comments [5] - Trackback

Filed under: Programming | Tools | Visual Studio

Most of our Visual Studio solutions contain hundreds of files (classes) organized neatly into dozens of folders (namespaces), but despite all of this organization the vertical content size of the Solution Explorer can get quite large. Finding a particular file when the majority of the tree is expanded is tedious and time-consuming, considering it should be a simple effort of less than five seconds. Fortunately, all of this is solved by the click of a button (assigned to handy macro).

The most useful macro for Visual Studio that I have ever encountered (and in the running for most useful VS tool, period) is the CollapseAll macro authored by one current and one former colleague, Dennis Burton and Mike Shields. In a quick XP effort, Dennis and Mike created a handy macro that recursively collapses the entire Solution Explorer tree down to just the solution and its projects.

With the tree collapsed, it is easy to find that desired file.

The macro is functional in all versions of Visual Studio for the Microsoft.Net framework, including Visual Studio 2003, Visual Studio 2005, and Visual Studio 2008.

CollapseAll Macro for Microsoft Visual Studio
Dennis Burton & Mike Shields | Published with Permission

Imports System
Imports EnvDTE
Imports System.Diagnostics

Public Module CollapseAll
    Sub CollapseAll()
        ' Get the the Solution Explorer tree
        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
            ' MsgBox("Nothing to collapse. You must have an open solution.")
            Return
        End If
        ' Get the top node (the name of the solution)
        Dim UIHSolutionRootNode As UIHierarchyItem
        UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1)
        UIHSolutionExplorer = Nothing
        UIHSolutionRootNode.DTE.SuppressUI = True
        ' Collapse each project node
        Dim UIHItem As UIHierarchyItem
        For Each UIHItem In UIHSolutionRootNode.UIHierarchyItems
            'UIHItem.UIHierarchyItems.Expanded = False
            If UIHItem.UIHierarchyItems.Expanded Then
                Collapse(UIHItem)
            End If
        Next
        ' Select the solution node, or else when you click
        ' on the solution window
        ' 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)
        UIHSolutionRootNode.DTE.SuppressUI = False
        UIHSolutionRootNode = Nothing
    End Sub

    Private Sub Collapse(ByVal item As UIHierarchyItem)
        For Each eitem As UIHierarchyItem In item.UIHierarchyItems
            If eitem.UIHierarchyItems.Expanded AndAlso eitem.UIHierarchyItems.Count > 0 Then
                Collapse(eitem)
            End If
        Next
        item.UIHierarchyItems.Expanded = False
    End Sub
End Module

Based on code from Edwin Evans

Here, the macro is so popular that it is a part of our default developer’s build for every new machine, and is conveniently assigned to a toolbar button. The default button icon list contains an Up Arrow (in the Change Button Image menu when customizing the toolbar) that seems quite appropriate. That little button has saved us all from a lot of pain, five seconds at a time.

Wednesday, 31 May 2006 10:19:55 (Eastern Daylight Time, UTC-04:00)  #    Comments [2] - Trackback

NAnt hates .Net’s resource files, or .resx. Don’t get me wrong–it handles them just fine–but large quantities of resx will really bog it down.

Visual Studio loves resx. The IDE will automatically create a resource file for you when you open pages and controls in the ‘designer’ view. Back when we still used Visual SourceSafe as our SCM, Visual Studio happily checked the file in and forgot about it. Now, our 500+ page application has 500+ resource files. Most of these 500+ resource files contain zero resources, making them useless, pointless, and a detriment to the build.

This morning I went through the build log, noting every resx that contained zero resources, and deleted all of these useless files.

The compile time dropped by 5 minutes.

Moral of the story: Be weary of Visual Studio. With regards to resx, VS is a malware program that’s just filling your hard drive with junk. If you use resx, great, but if you don’t, delete them all. NAnt will love you for it.

Wednesday, 15 February 2006 11:31:31 (Eastern Standard Time, UTC-05:00)  #    Comments [0] - Trackback

Filed under: ASP.Net | Programming | Tools | Visual Studio

“It compiles! Ship it!”

Microsoft has sent Visual Studio 2005 to the printers. That brings .Net 2.0 to the table in all of its glory. The official release date is still November 7, and though it is available now to all of us MSDN subscribers (though the site is too flooded to ping, let alone download), there is still some question on if the media will be ready in time to go in all of the pretty little VS05 boxes at your local Microsoft store.

Friday, 28 October 2005 13:40:03 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] - Trackback

With our new nightly database restore we now have the desire to automatically run all of the change scripts associated with a project. We’ve found a way; I created a NAnt script that will parse the Visual Studio Database Project (or "DBP") and execute all of the change scripts in it. Here’s how we got there.


Problem 1: Visual Studio Command Files are worthless

Our first idea was to have everyone update a command file in the DBP, and have NAnt run it every night. Visual Studio command files are great and all, but we have discovered a problem with them: they do not keep the files in order. We have named all of our folders (01 DDL, 02 DML, etc) and our change scripts (0001 Create MyTable.sql, 0002 AddInfoColumn to MyTable.sql) accordingly so that they should run in order. We have found that the command file feature of VS.Net 2003 does not keep them in order but rather seems to sort them first by extension, then by order, or some similar oddness. Obviously, if I try to at InfoColumn to MyTable before MyTable exists, I’m going to have a problem. So, the command file idea was axed.

Problem 2: Visual SourceSafe contents can’t be trusted

Our second idea was to VSSGET the DBP directory in VSS and execute every script in it. However, the VSS store cannot be trusted. If a developer creates a script in VS.Net called ‘0001 Crate MyTable.sql’ and checks it in to the project, then proceeds to correct the spelling error in VS.Net to ‘0001 Create MyTable.sql’, VS does not rename the old file in VSS. Instead, it removes the old file from the project, renames it locally, then adds the new name to the project and to VSS. It also never deletes the old file name from the VSS store. Now, both files (’0001 Crate MyTable.sql’ and ‘0001 Create MyTable.sql’) exist in VSS. Performing a VSSGET and executing all scripts will run both scripts, which could lead to more troubles.


So, we can’t use a command file, because it won’t maintain the order. We can’t trust VSS, since it can have obsolete files. We can only trust the project, but how do we get a list of files, ourselves?

Fortunately, DBP files are just text in a weird XML-wannabe format. The NAnt script will open the file and run through it looking for every ‘SCRIPT’ entry in the file. If it finds a ‘BEGIN something’ entry, it assumes that ’something’ is a folder name, and appends it to the working path until it finds ‘END’, at which time it returns to the parent directory.

It’s not perfect. It still runs in to some problems, but here it is in v0.1 form.

<project name="RunDBPScripts" default="RunScripts">
<!–-
Execute all scripts in a VS.Net DBP
Author: Jay Harris, http://www.cptloadtest.com, (c) 2005 Jason Harris
License: This work is licensed under a  
   Creative Commons Attribution 3.0 United States License.  
   http://creativecommons.org/licenses/by/3.0/us/ 

This script is offered as-is.
I am not responsible for any misfortunes that may arise from its use.
Use at your own risk.
-–>
<!-– Project: The path of the DBP file –->
<property name="project" value="Scripts.dbp" overwrite="false" />
<!-– Server: The machine name of the Database Server –->
<property name="server" value="localhost" overwrite="false" />
<!-– Database: The database that the scripts will be run against –->
<property name="database" value="Northwind" overwrite="false" />
<target name="RunScripts">
        <property name="currentpath"
            value="${directory::get-parent-directory(project)}" />
        <foreach item="Line" property="ProjectLineItem" in="${project}">
            <if test="${string::contains(ProjectLineItem, 'Begin Folder = ')}">
                <regex pattern="Folder = &quot;(?’ProjectFolder’.*)&quot;$"
                    input="${string::trim(ProjectLineItem)}" />
                <property name="currentpath"
                    value="${path::combine(currentpath, ProjectFolder)}" />
            </if>
            <if test="${string::contains(ProjectLineItem, 'Script = ')}">
                <regex pattern="Script = &quot;(?’ScriptName’.*)&quot;$"
                    input="${string::trim(ProjectLineItem)}" />
                <echo message="Executing Change Script (${server+"\"+database}): ${path::combine(currentpath, ScriptName)}" />
                <exec workingdir="${currentpath}" program="osql"
                    basedir="C:\Program Files\Microsoft SQL Server\80\Tools\Binn"
                    commandline=’-S ${server} -d ${database} -i “${ScriptName}" -n -E -b’ />
            </if>
            <if test="${string::trim(ProjectLineItem) == 'End’}">
                <property name="currentpath"
                    value="${directory::get-parent-directory(currentpath)}" />
            </if>
        </foreach>
    </target>
</project>

I used an <EXEC> NAnt task rather than <SQL>. I found that a lot of the scripts would not execute in the SQL task because of their design. VS Command Files use OSQL, so that’s what I used. I guess those command files were worth something after all.

If you know of a better way, or have any suggestions or comments, please let me know.

Thursday, 25 August 2005 12:15:41 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] - Trackback