Author's note: Following are some of the hacks from my book that stand out to me for different reasons. "Master the Command Window" (Hack #46) is one of the most time-saving and keyboard-friendly parts of Visual Studio. "Create Comments Faster" (Hack #69) is one of my favorite hacks since it covers one of my all-time favorite add-ins and is written by Roland Weigelt, creator of the add-in. "Run Unit Tests Inside Visual Studio" (Hack #93) covers one of my other top picks for add-ins, TestDriven.NET. It's one of the only add-ins that can really affect the way that you go about writing code. "Hack the Project and Solution Files" (Hack #4) is an interesting hack because it covers one of the undocumented parts of Visual Studio. I also selected "Refactor Your Code" (Hack #14) because it covers what I think is hands-down the best new feature in Visual Studio 2005, the Refactor menu.
|
Related Reading
Visual Studio Hacks |
![]()
![]()
Although Visual Studio is, er...well, rather visual, command-line junkies don't need to fear it.
Visual Studio has hundreds of menus, windows, and dialog boxes. This you are probably aware of; what you may not be aware of is that you can avoid using all of these and use the command line inside the command window instead. This hack looks at some of the different commands available to you, how to use existing aliases, and how to create and manage your own aliases.
So why would you want to use a command window when you could just use some part of the IDE? Using the command window is sometimes faster than using the IDE, and when you are writing code with both of your hands on the keyboard, it is often easier and faster to type a command than to reach for the mouse. Many people who are used to the good old days of the command prompt find themselves right at home with the command window, but whether or not you are one of these people, I encourage you to explore its functionality.
The main keystroke to remember is Ctrl-Alt-A (View.CommandWindow); this is the shortcut to open the command window.
The open command is the first command I am going
to cover. Using the open command, you can open any
file in either the filesystem or the current solution. (I think the
real added value here is opening a file in the current solution,
since the command window provides IntelliSense.) Figure 6-2 shows the command window and the
IntelliSense available for
the open command.

Figure 6-2. Command Window open command
This might not seem like much, but if you have a dozen projects with hundreds of files, this becomes much faster than digging through the Solution Explorer with your mouse.
You can use any Visual Studio command directly through the command window (through this book, whenever we mention a keyboard shortcut, we've also been mentioning the command). Any command can be used through the command window.
Twenty of the most useful commands are shown in Table 6-1. You can either type the full command or use the alias.
|
Command |
Alias |
Description |
|---|---|---|
|
File.OpenFile |
open |
Opens the file specified as a parameter |
|
File.NewFile |
nf |
Creates and opens a new file |
|
File.NewProject |
np |
Creates and opens a new project |
|
File.AddNewProject |
addProj |
Creates and adds a new project to the current solution |
|
File.SaveAll |
SaveAll |
Saves all the currently open files |
|
File.Close |
close |
Closes the selected file |
|
View.FullScreen |
FullScreen |
Switches to full-screen mode in the IDE |
|
View.Toolbox |
toolbox |
Shows the toolbox window |
|
View.PropertiesWindow |
props |
Shows the properties window |
|
Edit.GotoBrace |
GotoBrace |
Skips to the corresponding brace (e.g., the closing brace of an if statement) |
|
Edit.SelectAll |
Selects all the text in the current document | |
|
Edit.Undo |
undo |
Equivalent to Edit → Undo |
|
Edit.Redo |
redo |
Equivalent to Edit → Redo |
|
Edit.NextBookmark |
NextBook |
Jumps to the next bookmark |
|
Edit.PreviousBookmark |
PrevBook |
Jumps back to the previous bookmark |
|
Edit.CollapsetoDefinitions |
StopOutlining |
Collapses all collapsible section of code (classes, regions, etc.) |
|
Build.BuildSolution |
build |
Builds the current solution |
|
Debug.Print |
? |
Shows the value of the variable passed in as a parameter |
|
Debug.QuickWatch |
?? |
Displays the quick watch dialog for the variables passed in as a parameter |
|
Tools.Alias |
alias |
Lists all currently defined aliases or defines a new one |
When in doubt, you can sometimes fall back on old
MS-DOS
command prompt habits: for instance, the command
cls will clear the command window. You can
find a complete list of commands in the Tools → Options
→ Keyboard screen [Hack #24] .
Perhaps the most useful function of the command window is the ability to use it to view the values of variables during the debugging process. You can use a number of different commands during the debugging process to read and set the values of variables. You can simply type a question mark, a space, and then the name of a variable, and when you press Enter, the value of that variable will be printed to the screen. Here is an example of this command:
>? i
0
In this example, the value of the variable i is
zero. You can also set the value of a variable through the command
window by using the question mark, a space, the name of the variable,
and then an equals sign and the value that you want to set the
variable to. Here is an example of setting the value of a variable
through the command window:
>? i =2
2
As an alternative to using the question
mark, you can also set the command window to immediate
mode; this turns the command window into an
immediate window and you no longer need to use a question mark. You
can set the command window to immediate mode by typing in the command
immed. Following is a transcript of using the
command window in immediate mode:
>immedi
0
To switch the command window back into command
mode, you simply need to type in any command prefixed with
>. For instance, you could type
>cmd and the window would switch back to
command mode.
Another benefit to viewing the value of a variable in the command window is that it is easy to copy the value of that variable out of the command window. If you are working with a large string of XML, it might be valuable to get the value of that XML document and then copy it to your favorite XML application to view the data in a friendlier format.
Aliases are a way of creating a custom
command that is short for a longer command. The
Open command shown earlier is actually an alias
that Visual Studio defines for the more verbose command
File.OpenFile. To create new aliases you simply
need to type alias, the name of the alias,
then the command that you want to execute for this alias. Here is an
example of creating an alias for the
Edit.SelectAll command:
>alias selectall Edit.SelectAll
You can now select all the text on the screen by calling the alias
selectall. You can also create aliases that
include a parameter for a command. You can create a command called
openClass1 that calls the
File.OpenFile command and also
specifies which file to open. Here is an example of this command:
>alias openClass1 File.OpenFile Class1.cs
>openClass1
This way you can call the
openClass1 command at any time to open the
Class1.cs file. You can also remove aliases that
you have already created by simply adding the
/delete switch at the end of the alias
command. Here is an example of how to remove the
openClass1 alias:
>alias openClass1 /delete
While you can create and edit aliases directly in the command window, the VSTweak power toy provides an easy-to-use graphic interface for these command window aliases. Using this interface, you can add, edit, or delete command window aliases.
The VSTweak power toy is one of the more useful power toys for Visual Studio and is the subject of a number of different hacks in this book. The VSTweak power toy [Hack #13] can be downloaded from http://workspaces.gotdotnet.com/vstweak. Figure 6-3 shows an example of this interface.

Figure 6-3. The VSTweak Alias Manager
Using the Alias Manager, you can create, edit, and delete aliases using a nice graphical interface. The Available Commands button will show all of the available commands that you can create aliases for. The View File button shows the aliases.ini file, which stores all of the command window aliases.
The command window offers a lot of features that can be used to increase your productivity while working with Visual Studio, particularly when debugging.
|
![]()
![]()
There are boring parts of the XML commenting process that you can automate to make documentation more fun (and more likely to happen).
The problem with XML documentation
comments is that somebody has to write them. Even worse, often enough
that someone is you. The Visual Studio IDE helps you by preparing an
empty template when
you type /// in front of a method, but in the end
you still have to fill in the blanks.
Here's an example. Imagine a method "AppendHtmlText" that is used to append HTML text to some sort of buffer. This method has several overloads, and one of these overloads has a parameter of type "HtmlProvider". This is what Visual Studio will create when you start writing a new XML documentation comment:
/// <summary>
///
/// </summary>
/// <param name="htmlProvider"></param>
public void AppendHtmlText(HtmlProvider htmlProvider)
{
...
}
You would then add your text, so the XML documentation comment could, for example, look something like this:
/// <summary>
/// Appends the HTML text of the specified provider.
/// </summary>
/// <param name="htmlProvider">The HTML provider.</param>
public void AppendHtmlText(HtmlProvider htmlProvider)
{
...
}
This is a typical method that comes by the dozen: the method name pretty much says what it is doing and you definitely do not need much imagination to write the comment—after some time, these methods become a real drain to document. On the other hand, you simply have no choice. If you want the benefits of XML documentation comments (perhaps a nice help file generated by NDoc [Hack #71] ), you have to comment all public (and protected) members, period.
Let's take a closer look at the earlier example. The method is written according to Microsoft's Design Guidelines for Class Library Developers; some of these rules are:
Identifier names consisting of multiple words are written in PascalCasing (the method name) or camelCasing (the parameter name).
Acronyms are treated like normal words and are formatted accordingly (for example, "Html" instead of "HTML").
Identifier names do not contain abbreviations.
Method names usually start with a verb.
Now when you look at this set of rules on one hand and the documentation you have written on the other, it is pretty safe to say that a large part of the documentation could have been generated automatically.
GhostDoc is an add-in for Visual Studio .NET 2003 that tries to do just that. With GhostDoc installed, you move the cursor into the method or property you want to document, invoke the Document This command using either the source editor's context (right-click) menu or a hotkey, and GhostDoc will create an XML documentation comment. The result for the previous example would be:
/// <summary>
/// Appends the HTML text.
/// </summary>
/// <param name="htmlProvider">The HTML provider.</param>
public void AppendHtmlText(HtmlProvider htmlProvider)
{
...
}
Pretty close—but how does GhostDoc do that? First of all, it's important to note that the add-in has no idea of what the identifiers actually mean—GhostDoc simply assumes that the code is written according to the guidelines and does the following:
It breaks up identifier names into single words by analyzing the casing.
A word consisting of only consonants (for example, "HTML") is automatically treated as an abbreviation (other abbreviations, for example, "UML," can be specified explicitly).
For methods, the first word is treated as a verb and thus an s (in some cases es) is added.
A "the" is added between the first and the second word of the method name (unless the second word belongs to a configurable list of words that are never preceded by a "the").
After GhostDoc has created the XML documentation comment, the
developer has to edit only a few details (for example, for the
AppendHtmlText method, add "using
the specified provider" to the end of the sentence)
before moving on to the really interesting part of the documentation:
remarks on usage, references to related methods or properties,
example code—information that cannot be created automatically.
GhostDoc is driven by generation rules. When an XML documentation comment is about to be generated, the add-in will collect information about the code element (method, property, indexer, etc.) like name, return type, parameter names and types, and so on. This information is then compared to a set of rules, and the rule that fits best is then used to generate the documentation.
With each version of GhostDoc, the number of rules grows; the more specialized they are (for example, rules for handling Boolean properties, methods with a name consisting of only one word, etc.), the better the results.
Here are a few more examples that show only a part of what GhostDoc can automatically generate:
Note that the rule for indexers takes the name of the parameter into account, so it is "at the specified index", but "with the specified name":
/// <summary> /// Gets the <see cref="System.String"/> at the specified index.
/// </summary> /// <value></value> public string this[int index]
{
get { ... }
}
If you comment Boolean properties in .NET Framework documentation style, you will definitely recognize the "Gets or sets a value indicating whether..." rule, and most likely you already have stopped counting the times you have typed this phrase:
/// <summary> /// Gets or sets a value indicating whether
/// this <see cref="Demo"/> is cool.
/// </summary> /// <value> /// <c>true</c> if cool; otherwise, <c>false</c>.
/// </value> public bool Cool
{
get { return true; }
set { ; }
}
The so-called "of the" reordering is triggered by specific words such as "size," "length," or "name" (the list of trigger words can be configured):
/// <summary> /// Determines the size of the page buffer.
/// </summary> /// <param name="initialPageBufferSize">
/// Size of the initial page buffer.</param>
/// <returns></returns>
public int DeterminePageBufferSize(int initialPageBufferSize)
First, you will need to download and run the GhostDoc installer from http://www.roland-weigelt.de/ghostdoc.
After running the GhostDoc installer, the next time you start Visual Studio, a couple of configuration dialogs appear to complete the setup (for example, choose a hotkey). Note that GhostDoc cannot install a hotkey if Visual Studio is not already using a custom keyboard scheme—this is a limitation of Visual Studio's extensibility model. If you are not sure, simply try to assign a hotkey; if GhostDoc setup encounters a problem, it will tell you what to do.
GhostDoc comes with a C# source file that demonstrates the features of this add-in; simply load the demo project, which can be found in a subdirectory of the folder GhostDoc was installed to. Inside Visual Studio, open the Demo.cs C# file, move the cursor into the body of a method, for example, and invoke the Document This command. The Document This command can be invoked using the hotkey, from the right-click menu, or from Tools → GhostDoc → DocumentThis.
After you invoke the Document This command, GhostDoc will go to work and generate as much of your XML comments as it can.
Certain aspects of GhostDoc can be configured:
Which words are treated as acronyms
Which words must not be preceded by "the"
Which words trigger the "of the" reordering of an identifier name's words
The fixed parts of the generated texts.
You can edit the configuration settings in the dialog that is opened Tools → GhostDoc → Configure GhostDoc. This dialog is shown in Figure 8-2.

Figure 8-2. GhostDoc Configuration dialog
In this dialog, you can also export settings to a file that can then be imported on a different computer. This is pretty handy if, for example, you want to keep the configurations at home and at work in sync.
—Roland Weigelt
|
![]()
![]()
Testing can be just a few clicks away when you use TestDriven.NET to run unit tests right inside of Visual Studio.
Test Driven Development is the practice of writing unit tests for your code before you actually write that code. By writing a test and then writing the code to make that test pass, you have a much better idea of the goal and purpose of your code. Test Driven Development also encourages complete code coverage, which not only increases the quality of your code, but also allows you to refactor the internals of a method or class and quickly and easily test the outside interface of the object.
TestDriven.NET is a unit-testing add-in for Visual Studio. It was developed for a number of years under the name NUnitAddIn. It now supports multiple unit testing frameworks and is compatible with all versions of Visual Studio .NET. It is available in free and professional versions from the TestDriven.NET web site at http://www.testdriven.net. Its author, Jamie Cansdale, keeps a web log charting TestDriven.NET's development at http://weblogs.asp.net/nunitaddin.
TestDriven.NET can be installed using an administrator or limited user account. By default, it will install for just the current user. Because limited users don't have write access to the Program Files folder, a limited user installation will install files in the user's Application Data\TestDriven.NET folder. An administrator installation will install files in the Program Files\TestDriven.NET folder. These defaults can be changed by selecting Custom on the Choose Setup Type page.
TestDriven.NET is packaged with functional versions of the NUnit and MbUnit unit testing frameworks. It also includes an adapter for executing Visual Studio Team System unit tests when available. These will be installed to subdirectories inside the TestDriven.NET directory, as shown in Figure 13-2.

Figure 13-2. TestDriven.NET Setup
The Run Test(s) command offers a straightforward way to build and run tests. It is intended to be the default method of test execution in most contexts. It automatically detects the test framework being used and executes tests using the correct test runner. The tests are launched by a test execution engine running as an external process. This test process is kept alive in order to improve execution times on subsequent runs. Once a test process has been cached, a rocket icon will appear in the notify box.
If the code editor window is selected, the test(s) to execute will be determined by the position of the caret. Individual tests are executed by right-clicking anywhere inside a test method and selecting Run Test(s), as shown in Figure 13-3. All tests in a test fixture are executed by right-clicking inside a class (but outside of any method) and selecting Run Test(s). All tests in a namespace are executed by right-clicking inside a namespace and selecting Run Test(s).

Figure 13-3. Run Test(s) menu item
The Run Test(s) option is also found on various Solution Explorer context menus. It can be used to execute all tests in a solution, project, or project item.
Ad hoc tests offer a useful alternative to throwaway console applications. They should not in any way act as a substitute for real unit tests. Rather, they are intended to provide a convenient way of exploring local private methods or third-party code.
Any method that does not take parameters
can be executed as an ad hoc test simply by right-clicking inside it
and selecting Run Test(s). It can be a public, private, static, or
instance method. In the case of an instance method, an object will be
created using the default constructor of the class (providing, of
course, that the class has a default constructor). The
Dispose method will be called on any object that
implements IDisposable, once the test has been
executed.
If an ad hoc test returns an argument, the argument will be expanded to the Test output pane. Complex objects will have their fields and properties displayed. Enumerable objects will be listed. Primitive objects will be converted to strings and displayed.
The Test output pane is the window in which all test results and warning messages appear and is shown in Figure 13-4. Trace and debug information is also sent there, along with console output and error messages. If all tests in a project or solution are being executed, the Test output pane will display only ignored or failed tests.
When a test fails, the name of the test, together with the exception message and stack trace, is displayed. If code has been compiled with debugging information, the corresponding portions of the stack trace will contain line numbers. Double-clicking on these portions is a convenient way of navigating to the offending code.
As well as sending information to the output pane, failing tests also get added to the task list. If many tests have failed, this creates a useful summary view as shown in Figure 13-5. Generally, the further up the stack trace, the more likely the code will be of interest. Double-clicking a test in the task list is an alternative way of accessing the code in question.
The Test With... menu offers many alternative contexts in which to run tests. Selecting the Debugger context executes test(s) with the Visual Studio debugger attached, as shown in Figure 13-6. By setting a breakpoint on a method and selecting Test With... → Debugger, it is possible to step into a unit test.

Figure 13-6. Debugger command on Test With... submenu
By default, Visual Studio will build all projects in a solution when executing with the debugger. In Visual Studio .NET 2003 and Visual Studio 2005, there is an option to "Only build startup projects and dependencies on Run". Checking this option can significantly improve startup times when debugging large solutions. In Visual Studio .NET 2003, this option is under Tools → Options → Environment → Projects and Solutions. In Visual Studio 2005, it can be found under Tools → Options → Environment → Projects and Solutions→Build and Run.
By right-clicking on a project in the Solution Explorer window and selecting Run Test(s), all tests within that project will be executed. Failed and ignored tests are sent to the Test output pane and task list in a similar fashion to other Run Test(s) commands. Trace, debug, and console output is suppressed when executing all tests in a project or solution.
Similarly, all tests in a solution can be executed by right-clicking on the solution in the Solution Explorer window and selecting Run Test(s). For each project in the solution, the test framework being used is established and tests are executed using the correct test runner. Projects that do not contain any tests are simply ignored.
When a test run is in progress, an Abort Test menu item will appear on the Tools menu, as shown in Figure 13-7. Selecting this item will abort the thread the tests are executing on. When tests are aborted in this way, any cleanup logic is given a chance to run.

Figure 13-7. Abort Test command on Tools menu
You will sometimes need to stop the test process. The most common of these circumstances is when an app domain is created, but not unloaded by a test run. This can result in any assemblies loaded by the app domain being locked, which causes subsequent builds to fail. It is possible to recycle the test process by right-clicking on the rocket icon in the notify box and selecting Stop, as shown in Figure 13-8. A new test process will be launched the next time the Run Test(s) command is executed.

Figure 13-8. Stopping the test process
—Jamie Cansdale
|
![]()
![]()
Discover the format of these two Visual Studio files and learn about a tool to convert these files between versions of Visual Studio.
Solution and project files are an essential part of working with Visual Studio. You will almost always work with the solution and project files through the IDE, whether adding projects to your solution or configuring your project. The purpose of this hack is to describe the format of these files for two reasons. If your project or solution files become corrupted, knowing the structure of these files might help you fix the file without having to re-create the entire project or solution. Also, knowing the structure of these files will help you if you want to convert these files or write a tool that works directly with these files.
WARNING You must edit these files with extreme care. The format of these files is not published or documented and could change drastically in future versions. You should normally need to work with these files only through the IDE, and unless you find a compelling reason to, I would not directly edit these files. If you are interested only in converting the version of these files, then you may want to look toward the end of this hack under Section 1.5.3 to read about a tool that will do the conversion for you.
Visual Studio creates two separate files when you create a new solution in Visual Studio. The first file is the .suo (solution user options) file, which stores user settings such as the location of your breakpoints. This file is stored in binary format, which does not lend itself to easy editing. Since there are no compelling reasons to edit this file, I am not going to document the format of it here. If you think that this file is preventing your solution from opening, you can actually delete the file and Visual Studio will create a new one when you open the solution and save it when you close the IDE. By deleting the file, you will lose any of your user-specific settings like breakpoints, but this is a small price to pay for saving your solution. The .suo file is a hidden file, so you will need to make sure Windows Explorer is configured to show hidden files (this can be set through Tools → Folder Options → View in any Explorer window).
The second file that Visual Studio creates is the .sln file. This file stores information about the projects that make up this solution, source control settings, and other global settings that apply to all of the projects in the solution.
The first line of the solution file contains a declaration including the version of Visual Studio that this solution is built for:
Microsoft Visual Studio Solution File, Format Version 8.0
The version number used in the solution file is a little different than the version number you are used to seeing in the Visual Studio product name. Visual Studio .NET 2002 solution files have a version number of 7.0. Visual Studio .NET 2003 solution files have a version number of 8.0 (as opposed to the 7.1 number you are used to), and Visual Studio 2005 solutions files have a version number of 9.0. Visual Studio 2005 Beta 1 contains an additional line under this first line, which contains just the following:
# Visual Studio 2005
This line causes the icon of the file to be changed to a Visual Studio 2005-specific icon, and if removed, will prevent Visual Studio from opening this file when you double-click on it.
The next portion of the solution file contains a section for each of the projects that are contained in this solution:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HacksWinApp",
"HacksWinApp\HacksWinApp.csproj",
"{75B7D1AE-1896-409D-B717-64D9AFCF0F59}"
ProjectSection(ProjectDependencies) = postProject
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4} =
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HacksLib",
"HacksLib\HacksLib.csproj", "{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
You can see that the syntax of the file is somewhat similar to Visual
Basic. Each project has a
Project and EndProject tag as
well as a
ProjectSection tag to track the
dependencies for the project. The first
GUID in the project
tag is used to identify what type of project this is. In this
instance, the GUIDs for both a C# Windows Forms project and a C#
library project are the same, since these project types are really
the same except for the output type setting. The strings on the right
side of the equals sign include the name of the project, its path
relative to the solution root, and the unique GUID for this project.
This GUID is used for a number of things including tracking
dependencies.
TIP: You can view a list of all the project GUIDS by opening regedit (Start → Run, then type
regedit) and navigating to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\Projects.
Under this key are all the GUIDs for the project available on your machine; the name and the extension of the project are listed as well.
In Visual Studio .NET 2003 and Visual Studio 2005, project dependencies are also tracked here. These are not the implicit dependences that are created by project references. When Project A references Project B, there is an implicit dependency. Project B must be built before Project A since it references the other project's output. Since this type of dependency is project-specific information, it is stored in the project file. (In this example, it would be stored in Project A's project file since it is referencing Project B, rather than the solution file we are looking at here.) Project files and dependencies are described in the next section.
The dependences stored in the ProjectSection tag
are configured at the solution level. They define when a project must
be built before another project, but they may not directly reference
each other. This is stored in the ProjectSection
tag of the project that is dependent on the other project. In this
example, the HacksWinApp project is dependent on
the HacksLib project and thus includes a
reference to the GUID of the other project. This dependency is
normally configured by right-clicking on the solution file, selecting
Properties from the context menu, and navigating to Project
Dependencies in the property page that appears.
Visual Studio .NET 2003
includes a ProjectSection tag even if there is no
dependency (you can see this in the HacksLib
project tag). Visual Studio 2005 completely omits the
ProjectSection tag if there are no dependencies
for the project. Visual Studio .NET 2002 stores the dependency
information in a completely different section of the solution file,
which we will cover next.
The next section in the solution file is the
Global section, which begins with a
Global tag and ends with an
EndGlobal tag. Inside these tags are a number of
GlobalSection tags that store an array of different
pieces of information, including the configuration settings for
various projects as well as source control information. Here is a
look at the Global section of this example solution file from Visual
Studio .NET 2003:
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{75B7D1AE-1896-409D-B717-64D9AFCF0F59}.Debug.ActiveCfg
= Debug|.NET
{75B7D1AE-1896-409D-B717-64D9AFCF0F59}.Debug.Build.0
= Debug|.NET
{75B7D1AE-1896-409D-B717-64D9AFCF0F59}.Release.ActiveCfg
= Release|.NET
{75B7D1AE-1896-409D-B717-64D9AFCF0F59}.Release.Build.0
= Release|.NET
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}.Debug.ActiveCfg
= Debug|.NET
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}.Debug.Build.0
= Debug|.NET
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}.Release.ActiveCfg
= Release|.NET
{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}.Release.Build.0
= Release|.NET
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal
The
SolutionConfiguration and
ProjectConfiguration sections contain the
build
configuration settings for the solution and its projects. The
ExtensibilityGlobals and
ExtensibilityAddIns sections are included for the
benefit of add-in authors. The
ExtensibilityGlobals section can be used to store
global information about the solution, and the
ExtensibilityAddIns section lists all
the
add-ins that are used in this solution.
Visual Studio .NET 2002 also uses the Global
section to store information about project
dependences. Here
is an example of that configuration section:
GlobalSection(ProjectDependencies) = postSolution
{1C19F285-69AF-409E-8D5B-A354B68B41FF}.0
= {CBBAD9B0-CB56-44CA-8312-A9258F2061E2}
EndGlobalSection
This section simply specifies that the project identified by its GUID on the left of the equals sign depends on the project identified by its GUID on the right side of the equals sign.
Visual Studio 2005 includes an additional section that is not present in any of the older versions of Visual Studio; it's shown here:
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
If the FALSE is switched to TRUE, then the solution node is hidden in the IDE.
Each project creates a number of files to store information about itself. This includes a project file and a user settings file. The extension for the project file is based on the language type; for example, a C# Project is saved with the extension .csproj and a VB.NET Project is stored with the extension .vbproj. Thankfully, the internal formats of these various files are based on the same XML schema. The beginning of each project file includes some basic information about the project, including the version of Visual Studio that it was created for as well as the GUID for this project. Here is an example of this section:
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.10.3077"
SchemaVersion = "2.0"
ProjectGuid = "{89EE0E8E-C5C6-4772-A5EE-D347E40FB0E4}"
>
This is from a Visual Studio .NET 2003 project file, which is why the
ProductVersion is set to 7.1 and the
SchemaVersion is set to 2.0. In Visual Studio .NET
2002, the ProductVersion would be 7.0 and the
SchemaVersion would be 1.0. These settings are no
longer relevant in Visual Studio 2005 as project files are now
MSBuild files.
TIP: Notice that the version number used for Visual Studio .NET 2003 is 7.1 in the project file and 8.0 in the Solution file.
The next
section of the project file is the Build section,
which includes build settings and configuration settings as well as
references information. Here is the Build settings
section:
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "HacksLib"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Library"
PreBuildEvent = ""
PostBuildEvent = ""
RootNamespace = "HacksLib"
RunPostBuildEvent = "OnBuildSuccess"
StartupObject = "">
As you can see, this section includes information like the
AssemblyName and
OutputType of the project. The
next part of the Build section is for the various
build configurations:
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = ""
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"/>
This section includes configuration-specific build settings. The
project file will usually contain at least a Debug
and Release section. The next part of the
Build section contains all of the references for
this project. Here is an abbreviated example of this section:
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath = "..\..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\
Framework\v1.1.4322\System.dll"
</References></Build>
The
References section contains a reference tag for
each assembly referenced by the project. Starting with Visual Studio
2005, you can create a reference to either an assembly or an
executable, which comes in very handy when you are trying to
unit-test a Windows application, since this lets you directly
reference your application. To get this same functionality in Visual
Studio .NET 2003, you can actually hack the project file to create a
reference to an executable—you simply need to manually enter a
reference tag in the references element pointing to your executable.
Your new reference tag would look exactly like this example, except
it would be pointed to an .exe file instead of a
.dll file.
After the Build section is
theFiles section of the project file, which can be
seen here:
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Class1.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>
This section simply tracks all of the files that are included in this project. The schema of the project file is pretty straightforward in case you need to edit it directly.
Visual Studio also creates a user-specific project file much like the .suo file created for the solution file except with an extension of <projectextension>.user, so if you were using VB.NET, it would be vbproj.user. Similarly, this user-specific file does not contain anything pertinent enough to cover here, and is also hidden by default, so you will need configure Windows Explorer to show hidden files through Tools → Folder Options → View.
Visual Studio 2005 has not been mentioned up until this point because the project files in Visual Studio 2005 are completely different than the project files in Visual Studio .NET 2002 and 2003. The project files in Visual Studio 2005 are MSBuild XML files. MSBuild is the new build tool used in Visual Studio 2005 and is a completely different, complex topic that is not going to be covered here. It is similar to NAnt in that is uses XML files to describe how the project should be built.
Visual Studio does an excellent job of converting files from older versions to newer versions. For instance, if you open a Visual Studio .NET 2002 solution in Visual Studio .NET 2003, it will first ask if you want to convert the solution. After you say yes, it will convert all of your solution and project files to the new version of Visual Studio .NET. Now what if you accidentally converted those files and didn't have a backup? Or perhaps you are writing a solution in Visual Studio .NET 2003 and find out that your client has only Visual Studio .NET 2002? One method would be to create a new solution in the old version, create an identical project structure, and then copy all the files over and add them to their respective projects. Thankfully, there is a better solution. There is a tool available that will automatically convert the project and solution files for you as well as the .resx files if you are using Windows Forms.
The tool is called Visual Studio Converter 2.0 and can be downloaded from http://www.codeproject.com/macro/vsconvert.asp.
This tool is simple to use. Figure 1-15 shows an example of this conversion tool's user interface.

Figure 1-15. Visual Studio Converter 2.0
To convert files, you first need to click the Add Files button and select all the solution, projects, and .resx files for your solution. For a simple, one-form C# Windows Forms application, you would need to include the .sln, .csproj, .csproj.user, and Form1.resx. You will have an additional .resx file for each form in your application. Next, you need to click one of the two conversion buttons to convert the files to either Visual Studio 7.0 (2002) or Visual Studio 7.1 (2003). When initially converting a 2002 project to the 2003 format, it is best to use the Visual Studio conversion process. After this initial process, this tool is a great way to convert the files back and forth as needed.
Currently, it converts only between Visual Studio .NET 2002 and Visual Studio .NET 2003.
|
![]()
![]()
Visual Studio 2005 puts this fundamental tenet of Extreme Programming into action. Use it to write better code.
Refactoring is a technique for improving a section of code by modifying its internal structure, but without affecting its external behavior. Refactoring is one of the key tenets of Extreme Programming; in a rapid development methodology, the idea is to create code quickly and then refactor it as you work with it. The goal of Extreme Programming is to create better quality code by concentrating on small deliverables and continuously testing and refactoring your code. Refactoring is not just limited to Extreme Programming—it is a valuable practice regardless of the methodology you happen to subscribe to. Visual Studio 2005 introduces a new Refactor menu. This menu is available whenever you right-click and provides a number of time-saving and code-improving functions.
TIP: Refactoring is almost exclusively a C# feature. The only part of the Refactor menu that is available in VB.NET is the Rename function.
Figure 2-31 shows the menu and the various functions included there.
The first function available in the Refactor menu is Extract Method. This can be used to select a block of code and then extract that code into a separate method. This function has a number of applications, such as removing a section of code that deserves to be in its own method for code reuse purposes. Here is some existing code:
public class Car
{
private bool _isStarted = false;
private bool _hasFuel = true;
public Car( )
{
//Start the Car
if (_hasFuel){_isStarted = true;}
}
}
That example has a little bit of code in the constructor that checks
to see if the car has fuel and then
"starts" the car by setting a
Boolean value. If you decide that this class needs a second
constructor, instead of duplicating this tiny piece of logic, you
could extract this into a separate StartCar method
and then call that method from both constructors. To accomplish this
with the Refactor menu: highlight the code you want to extract and
then right-click and select the Extract Method function from the
Refactor menu. After you select Extract Method, you see a dialog box
that asks for the name of the new method (see Figure 2-32).

Figure 2-32. Extract Method dialog
Type in the new name of the method, in this case,
StartCar, since it describes exactly what the
method will accomplish. After you click OK, Visual Studio will modify
the selected code by placing it in a new method named
StartCar, then placing a call to the new method in
the spot where the old code was. Here is the new code:
public Car( )
{
//Start the Car
StartCar( );
}
private void StartCar( ){if (_hasFuel){_isStarted = true;}}
The second
function
on the Refactor menu is the Rename function. This is one of the most
time-saving functions on this menu. Suppose that you decide the name
Car is a little shortsighted, since the system
will need to work for Cars,
Bikes, Trucks, and more. A more
appropriate name would be Vehicle. Normally you
would need to manually find all references to the name
Car and change them; the Rename function does this
for you automatically. First, right-click on the name
Car and then select the Rename function from the
Refactor menu; the Rename dialog will then be displayed (see Figure 2-33). The Rename dialog allows you to specify what
to rename the class to; in this case, it's going
from Car to Vehicle. A number
of checkboxes are available; check all of them in this example. The
first (Preview Reference Changes) lets you preview all of the changes
to the files; the next two checkboxes (Search In Comments/Strings)
tells Visual Studio to search for this name in comments as well as
strings.
After clicking the OK button, you will see a confirmation dialog that
shows all of the changes that will be made. As you can see in Figure 2-34, the Preview Changes dialog shows where Visual
Studio is going to change the name Car to
Vehicle. After you click Apply, Visual Studio will
make all the changes to the project.
WARNING One thing that Visual Studio does not change is the name of the
StartCarmethod. Since Visual Studio does not look in method names when making these changes, you will have to changeStartCartoStartVehicleyourself.

Figure 2-34. Preview Changes dialog
In addition to being a great time-saver, Rename removes any excuse you might make about why a class is not named appropriately.
The Encapsulate Field function creates a
public property that encapsulates your
field.
In the ongoing example, suppose that you need to create a public
property for the _isStarted field. To do this,
right-click on the field name and click the Encapsulate Field
function on the Refactor menu. You are then shown the Encapsulate
Field dialog, which is shown in Figure 2-35.

Figure 2-35. Encapsulate Field dialog
Visual Studio automatically sets the property name to be
IsStarted and gives you the option to update
references to the old field. Leave this setting as External so that
code in your class is not changed to reference the public property
and instead continues to use the private field. The other checkboxes
are similar to the ones you saw in the Rename dialog and perform the
same actions. After you click OK, you are shown a Preview Changes
dialog--the same kind of dialog shown in Figure 2-34—which shows all of the
changes that will result. After you accept the changes shown, the following code
is added to the class:
public bool IsStarted
{
get
{
return _isStarted;
}
set
{
_isStarted = value;
}
}
This function comes in handy even when you are not refactoring. When creating a class for the first time, you can create the private fields and then use this function to create all of the necessary public properties.
The Extract Interface function
looks at your current
class and creates an
interface based on its public methods and properties. For example,
suppose you want to create an interface for objects that can be
"started"; this interface would
include a Boolean property, in this case
IsStarted, which, when set, has the side effect of
"starting" the object (some kind of
vehicle or item with an on/off switch). First, right-click on the
class name and click the Extract Interface menu item; this displays
the Extract Interface dialog, which is shown in Figure 2-36.

Figure 2-36. Extract Interface dialog
The default interface name is IVehicle; change it
to IStart and then select the
IsStarted property. After you click OK, Visual
Studio creates a new file called IStart.cs with
the following piece of code:
interface IStart
{
bool IsStarted { get; set; }
}
Visual Studio will also modify the existing class to implement the new interface. The Extract Interface function is a great time-saver when you need to create an interface that is based on a current class.
The next three functions on
the menu all focus on working with parameters. Since the sample class
does not currently contain any methods with parameters, go ahead and
add a new method with a number of different parameters. Here is a
method called Collision that you can add to this
class:
public void Collision(DateTime CrashDate, int Speed, int DamagePct)
{
int costMultiplier = 1;
// Do stuff
}
As you can see, this method has a local variable called
costMultiplier and sets the value to
1. But suppose that
costMultiplier varies from vehicle to vehicle. In
this case, you'd want to pass in this multiplier as
a parameter instead of creating it as a local variable. The first of
the parameter refactoring functions will do just that. First,
right-click on the costMultiplier variable and
select the Promote Local Variable
to Parameter function. This will take
the local variable and add it as a parameter to the method. Here is a
look at the modified code:
public void Collision(int costMultiplier, DateTime CrashDate,
int Speed, int DamagePct)
{
// Do stuff
}
You may be thinking that this is not a big deal; it is basically cut and paste. But Visual Studio also goes and looks for any calls to this method and modifies them as well. If you were calling this method before with the following line of code:
Collision(DateTime.Now, 60, 10);
this method call would be changed to the following:
Collision(1, DateTime.Now, 60, 10);
Notice that Visual Studio not only adds the new parameter, but also passes in the value that the local variable was set to as well, saving time and ensuring that existing code continues to work as it did before.
Suppose you decide that you don't need the
CrashDate parameter. If you won't
be using it in the method, you can remove this parameter using the
second of these parameter refactoring
functions, called Remove Parameters. First, right-click on the method
name and click Remove Parameters in the Refactor menu.
You'll be shown the Remove Parameters dialog, which
is shown in Figure 2-37.

Figure 2-37. Remove Parameters dialog
In the Remove Parameters dialog, you can select the
CrashDate parameter, click Remove, and then click
OK. You are then shown a Preview Changes dialog showing the changes
that will be made to any calls to this method. After clicking Apply
on that screen, those changes will be made. Any calls to this method
will have this parameter removed, and the parameter will be removed
from the method signature.
Further, suppose you decide that you don't want
costMultiplier to be the first parameter, but
rather the last parameter. This is where the last of the parameter
functions comes in. First, right-click on the method, then choose the
Reorder Parameters menu item on the
Refactor menu. This will display the Reorder Parameters dialog, which
is shown in Figure 2-38.

Figure 2-38. Reorder Parameters dialog
You can then select the costMultiplier parameter,
move it down two spots, and click OK. You will again then be shown
the Preview Changes dialog. where you can confirm the changes that
will be made to any calls to this method. Click Apply, and the order
of the parameters will be changed in the method signature and any
calls to this method.
The Refactor menu is a great addition to Visual Studio and will make it much easier to refactor code. If you want to learn more about refactoring, the best resources are the book Refactoring (Addison-Wesley) and the companion web site, http://www.refactoring.com.
Tired of waiting for Visual Studio 2005 or stuck using Visual Studio .NET 2003 for some reason? A number of commercial tools are available that add similar functionality into Visual Studio .NET 2003:
From Jet Brains:
From XtremeSimplicity:
View catalog information for Visual Studio Hacks
Return to ONDotnet.com.
Copyright © 2009 O'Reilly Media, Inc.