<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Random Musings of Jeremy Jameson : Visual Studio</title><link>http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx</link><description>Tags: Visual Studio</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Bug Deploying SQL Server Database Using VSDBCMD.EXE</title><link>http://blogs.msdn.com/jjameson/archive/2009/12/09/bug-deploying-sql-server-database-using-vsdbcmd-exe.aspx</link><pubDate>Wed, 09 Dec 2009 14:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9934579</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9934579.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9934579</wfw:commentRss><description>&lt;P&gt;Yesterday we encountered a bug while trying to deploy a new SQL Server database from a Visual Studio database project using the VSDBCMD.EXE utility, following the prescriptive guidance on MSDN:&lt;/P&gt;
&lt;DIV class=reference&gt;&lt;CITE&gt;How to: Prepare a Database for Deployment From a Command Prompt by Using VSDBCMD&lt;/CITE&gt; 
&lt;DIV class=referenceLink&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd193258.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd193258.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd193258.aspx&lt;/A&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;According to this MSDN article, all you need to do is copy some files to the server running Microsoft SQL Server, and then run the VSDBCMD.EXE utility (specifying your .dbschema or .deploymanifest file).&lt;/P&gt;
&lt;P&gt;Unfortunately, when we attempted to deploy our database to our Test environment, we encountered a &lt;CODE&gt;NullReferenceException&lt;/CODE&gt;: &lt;/P&gt;
&lt;BLOCKQUOTE class="directQuote errorMessage"&gt;Object reference not set to an instance of an object.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Fortunately, it didn't take long to find &lt;A href="http://social.msdn.microsoft.com/Forums/en-US/vstsdb/thread/32725cf6-74c1-4b5a-9057-b909ae8a2517" mce_href="http://social.msdn.microsoft.com/Forums/en-US/vstsdb/thread/32725cf6-74c1-4b5a-9057-b909ae8a2517"&gt;Gert's recommendation&lt;/A&gt; to add the following registry key:&lt;/P&gt;
&lt;DIV class=consoleBlock&gt;&lt;SAMP&gt;reg add HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0&lt;/SAMP&gt;&lt;/DIV&gt;
&lt;P&gt;The error occurred since Visual Studio has never been installed on the SQL Server in TEST (unlike our local development VMs).&lt;/P&gt;
&lt;P&gt;It certainly would be nice if the above MSDN article were updated to note the bug and associated workaround.&lt;/P&gt;
&lt;BLOCKQUOTE class=note&gt;
&lt;DIV class=noteTitle&gt;Note&lt;/DIV&gt;
&lt;DIV&gt;As pointed out in a comment by Ramkumar Perumal, Microsoft.SqlServer.BatchParser.dll does not exist in any of the specified folders. This should also be reflected in the MSDN article.&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You will also find instructions to add the registry key -- as well as an explanation for why you more than likely already have Microsoft.SqlServer.BatchParser.dll installed on your SQL Server -- in the following blog post:&lt;/P&gt;
&lt;DIV class=reference&gt;&lt;CITE&gt;Deploying your Database Project without VSTSDB installed. 2009-02-21&lt;/CITE&gt; 
&lt;DIV class=referenceLink&gt;&lt;A href="http://blogs.msdn.com/bahill/archive/2009/02/21/deploying-your-database-project-without-vstsdb-installed.aspx" mce_href="http://blogs.msdn.com/bahill/archive/2009/02/21/deploying-your-database-project-without-vstsdb-installed.aspx"&gt;http://blogs.msdn.com/bahill/archive/2009/02/21/deploying-your-database-project-without-vstsdb-installed.aspx&lt;/A&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9934579" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>The "Copy Local" Bug in Visual Studio</title><link>http://blogs.msdn.com/jjameson/archive/2009/11/18/the-copy-local-bug-in-visual-studio.aspx</link><pubDate>Wed, 18 Nov 2009 12:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9924246</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9924246.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9924246</wfw:commentRss><description>&lt;P&gt;If you've ever worked with me on a Microsoft Office SharePoint Server (MOSS) 2007 project -- or if you've read my &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/09/28/sample-walkthrough-of-the-dr-dada-approach-to-sharepoint.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/09/28/sample-walkthrough-of-the-dr-dada-approach-to-sharepoint.aspx"&gt;Sample Walkthrough of the DR.DADA Approach to SharePoint&lt;/A&gt; -- then you've probably seen the following comment:&lt;/P&gt;
&lt;BLOCKQUOTE class=directQuote&gt;
&lt;P&gt;Note: Referenced assemblies must be specified with a path corresponding to the build configuration. If the path is not specified to the referenced assembly, then the build works fine as long as the referenced assembly is not in the GAC.&lt;/P&gt;
&lt;P&gt;However, when the referenced assembly is in the GAC (i.e. after a deployment) then MakeCAB will not be able to find the referenced assembly (since it is no longer copied to the current project's bin\Debug or bin\Release folder).&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It turns out that I was using a rather elaborate workaround for a problem that is actually much easier to solve.&lt;/P&gt;
&lt;P&gt;To workaround the "Copy Local" bug and force a referenced assembly to always be copied to the output folder (regardless of whether the referenced assembly is in the GAC):&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Solution Explorer &lt;/STRONG&gt;window in Visual Studio, expand the &lt;STRONG&gt;References&lt;/STRONG&gt; folder for the project and then select the referenced assembly.&lt;/LI&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Properties &lt;/STRONG&gt;window, change the value of &lt;STRONG&gt;Copy Local &lt;/STRONG&gt;to &lt;STRONG&gt;False&lt;/STRONG&gt;, and then change it back to &lt;STRONG&gt;True&lt;/STRONG&gt;.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Following these two simple steps explicitly adds &lt;CODE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Private&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;True&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Private&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/CODE&gt; to the project file, as shown in the following example:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ProjectReference&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;Include&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt;..\CoreServices\CoreServices.csproj&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
      &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Project&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;{01C58D27-9818-45D6-A0B6-8EF765CA9397}&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Project&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
      &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;CoreServices %28CoreServices\CoreServices%29&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
      &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Private&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;True&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Private&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ProjectReference&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;When you add a referenced assembly in Visual Studio using a project reference, &lt;STRONG&gt;Copy Local &lt;/STRONG&gt;defaults to &lt;STRONG&gt;True&lt;/STRONG&gt;, but Visual Studio doesn't explicitly state this in the MSBuild project file. Toggling the value of &lt;STRONG&gt;Copy Local &lt;/STRONG&gt;forces this element to be added to the project file and consequently you no longer need any hacks to reference the assembly in its original output folder.&lt;/P&gt;
&lt;P&gt;At this point, you might be wondering why do I bring this up after all this time? After all, hasn't the hack I came up with for building SharePoint Web Solution Packages (WSPs) been working for several years? Well, yes, in most cases it works just fine.&lt;/P&gt;
&lt;P&gt;However, there's one fundamental problem that I only recently discovered back in early October: you can't use Team Foundation Build to build the WSP when specifying relative paths to assemblies in the DDF file.&lt;/P&gt;
&lt;P&gt;I'll cover this in &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/11/18/building-sharepoint-wsps-with-team-foundation-build.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/11/18/building-sharepoint-wsps-with-team-foundation-build.aspx"&gt;my next post&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9924246" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/MOSS+2007/default.aspx">MOSS 2007</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/WSS+v3/default.aspx">WSS v3</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Recommendations for Code Analysis</title><link>http://blogs.msdn.com/jjameson/archive/2009/10/31/recommendations-for-code-analysis.aspx</link><pubDate>Sat, 31 Oct 2009 13:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9915654</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9915654.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9915654</wfw:commentRss><description>&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/10/31/recommended-check-in-policies-for-team-foundation-server.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/10/31/recommended-check-in-policies-for-team-foundation-server.aspx"&gt;previous post&lt;/A&gt;, I briefly mentioned the Code Analysis feature of Visual Studio in the context of using check-in policies with Team Foundation Server (TFS). However, there's a lot more to talk about with regards to using Code Analysis.&lt;/P&gt;
&lt;P&gt;If you are ever find yourself "starting from a clean slate" on a software development project, I hope you take advantage of the opportunity to not only enable Code Analysis, but also to treat all Code Analysis warnings as errors. That's right, go ahead and check all of those boxes (for both &lt;STRONG&gt;Debug &lt;/STRONG&gt;and &lt;STRONG&gt;Release &lt;/STRONG&gt;configurations, of course) so that whenever potential issues are reported by Code Analysis, it stops developers dead in their tracks and considers the build to be broken.&lt;/P&gt;
&lt;P&gt;While you're at it, go ahead and select the &lt;STRONG&gt;All &lt;/STRONG&gt;option in the &lt;STRONG&gt;Treat warnings as errors &lt;/STRONG&gt;section on the &lt;STRONG&gt;Build &lt;/STRONG&gt;tab (something I definitely recommend as a best practice). Again, be sure to do this for all build configurations.&lt;/P&gt;
&lt;P&gt;Yes, this is going to be really painful for some developers.&lt;/P&gt;
&lt;P&gt;For example, you can say goodbye to using the overload of string.Format() that doesn't specify a CultureInfo:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; foo = &lt;SPAN style="COLOR: #a31515"&gt;"here"&lt;/SPAN&gt;;

            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; logMessage = &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;.Format(
                &lt;SPAN style="COLOR: #a31515"&gt;"Imagine something interesting {0}."&lt;/SPAN&gt;,
                foo);&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;Attempting this will now result in a broken build:&lt;/P&gt;
&lt;BLOCKQUOTE class="directQuote errorMessage"&gt;Error 2 CA1305 : Microsoft.Globalization : Because the behavior of 'string.Format(string, object)' could vary based on the current user's locale settings, replace this call in 'Program.Main(string[])' with a call to 'string.Format(IFormatProvider, string, params object[])'. If the result of 'string.Format(IFormatProvider, string, params object[])' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify 'CultureInfo.InvariantCulture'. &lt;/BLOCKQUOTE&gt;
&lt;P&gt;To avoid the CA1305 error, you will need to use something like this instead:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; foo = &lt;SPAN style="COLOR: #a31515"&gt;"here"&lt;/SPAN&gt;;

            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; logMessage = &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;.Format(
                &lt;SPAN style="COLOR: #2b91af"&gt;CultureInfo&lt;/SPAN&gt;.InvariantCulture,
                &lt;SPAN style="COLOR: #a31515"&gt;"Imagine something interesting {0}."&lt;/SPAN&gt;,
                foo);&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;You will also need to enable signing of all assemblies with a strong name key, and also specify various assembly level attributes (e.g. &lt;A href="http://msdn.microsoft.com/en-us/library/system.clscompliantattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.clscompliantattribute.aspx"&gt;&lt;CODE&gt;[assembly: CLSCompliant(true)]&lt;/CODE&gt;&lt;/A&gt;). However, if you follow the steps I've provided in a &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx"&gt;previous post&lt;/A&gt;, this should only take you at most 1-2 minutes.&lt;/P&gt;
&lt;P&gt;Like I said before, this will probably cause some heartburn in the beginning, but trust me, developers will quickly get used to it and the code they write will be much better as a result.&lt;/P&gt;
&lt;P&gt;Now what about the other 99% of the time when you aren't starting from a clean slate, but instead are dealing with a substantial code base that causes the Code Analysis feature in Visual Studio to "light up like a Christmas tree" when you turn it on?&lt;/P&gt;
&lt;P&gt;Well, as with all software bugs, it all comes down to &lt;EM&gt;triage&lt;/EM&gt;. You obviously cannot simply halt all feature development in order to resolve code analysis issues. Instead, you should go for the "low hanging fruit" (meaning the issues that occur frequently but can be resolved with relatively little effort or risk of changing). You should also try to enable the Code Analysis rules that are most important, such as potential security issues.&lt;/P&gt;
&lt;P&gt;The following post provides some great information about which Code Analysis warnings to focus your attention on first:&lt;/P&gt;
&lt;DIV class=reference&gt;&lt;CITE&gt;What rules do Microsoft have turned on internally? 2007-08-09.&lt;/CITE&gt; 
&lt;DIV class=referenceLink&gt;&lt;A href="http://blogs.msdn.com/fxcop/archive/2007/08/09/what-rules-do-microsoft-have-turned-on-internally.aspx" mce_href="http://blogs.msdn.com/fxcop/archive/2007/08/09/what-rules-do-microsoft-have-turned-on-internally.aspx"&gt;http://blogs.msdn.com/fxcop/archive/2007/08/09/what-rules-do-microsoft-have-turned-on-internally.aspx&lt;/A&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;This article is obviously a little dated, but still very relevant over two years later.&lt;/P&gt;
&lt;P&gt;Note that you will undoubtedly need to &lt;A href="http://msdn.microsoft.com/en-us/library/ms244717.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms244717.aspx"&gt;suppress some specific Code Analysis warnings&lt;/A&gt; from time to time, and therefore you'll have to choose how to suppress the warnings (whether inline within the source, or in a GlobalSuppressions.cs file). However, I hope you'll choose to fix the underlying issue that causes the Code Analysis warning (whenever practical) instead of simply suppressing a bunch of warnings.&lt;/P&gt;
&lt;P&gt;So, in conclusion, think of the Code Analysis feature in Visual Studio as a way of &lt;EM&gt;choosing&lt;/EM&gt; a more strict compiler. For example, back in the days when I used to program in C on Unix, the compiler wouldn't complain when I wrote something like this (even though this is obviously very wrong):&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (i = 1)
            {
                ...
            }&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;I was relieved when I switched to C++ and these kinds of bugs were a thing of the past. [Note that I never switch my coding style to use something like "&lt;CODE&gt;1 == i&lt;/CODE&gt;" in order to avoid these errors.]&lt;/P&gt;
&lt;P&gt;Fortunately, in C# you don't have a choice about whether or not this compiles (it doesn't).&lt;/P&gt;
&lt;P&gt;I like to think of enabling all of the Code Analysis rules in a similar fashion. In other words, I want the compiler to tell me whenever I am doing something potentially wrong, because then I can spend just a little bit of time fixing my code to do it right. By forcing the Code Analysis warnings as errors, I don't have a choice -- meaning I have to fix them before check-in.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9915654" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Essential Add-Ins for Team Foundation Server</title><link>http://blogs.msdn.com/jjameson/archive/2009/10/25/essential-add-ins-for-team-foundation-server.aspx</link><pubDate>Sun, 25 Oct 2009 15:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9912619</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9912619.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9912619</wfw:commentRss><description>&lt;P&gt;In a &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/24/diffmerge-a-better-differencing-tool.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/24/diffmerge-a-better-differencing-tool.aspx"&gt;previous post&lt;/A&gt;, I mentioned how I use SourceGear's DiffMerge instead of the out-of-the-box tool that comes with Team Foundation Server (which is also called DiffMerge). If you haven't at least evaluated the SourceGear alternative, I definitely advise you to take a look.&lt;/P&gt;
&lt;P&gt;The other "add-in" for TFS that I consider to be essential is the &lt;A href="http://www.acorns.com.au/projects/vsaddins/" mce_href="http://www.acorns.com.au/projects/vsaddins/"&gt;TFS Quick Search Plugin&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;If you have Web access to your TFS instance (via &lt;A href="http://msdn.microsoft.com/en-us/teamsystem/bb980951.aspx" mce_href="http://msdn.microsoft.com/en-us/teamsystem/bb980951.aspx"&gt;Team System Web Access&lt;/A&gt;), then quickly locating work items by keywords is actually pretty easy. However if you either don't have access to Team System Web Access or you would simply rather prefer to search for a work item without leaving Visual Studio, then the TFS Quick Search Plugin is definitely the way to go.&lt;/P&gt;
&lt;P&gt;Note that it doesn't search all of the fields in all work items, but rather searches the work items currently displayed within Visual Studio. However, if you know a keyword that appears in the title of a work item, this can make it very easy to locate the desired work item.&lt;/P&gt;
&lt;P&gt;I tend to use the TFS Quick Search Plugin a lot for the scenario where I am trying to find a duplicate bug and I remember a couple of keywords in the title of the previous bug. It is certainly much faster than scrolling through a few hundred work items in order to find something, or trying to build a query on-the-fly in order to locate a work item.&lt;/P&gt;
&lt;P&gt;I am really interested to see the improvements in Visual Studio 2010 and Team Foundation Server 2010, but honestly it's probably going to be a while before I'm able to use that in my day-to-day work. Nevertheless, I hope this kind of work item "quick search" comes out-of-the-box in the next release (as well as a better DiffMerge tool). [I did do some hands-on labs back in February that cover the new branching visualization features in TFS 2010, and I have to say that I absolutely love what I've seen so far.]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9912619" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/TFS/default.aspx">TFS</category></item><item><title>Formatting Code for My Blog</title><link>http://blogs.msdn.com/jjameson/archive/2009/10/09/formatting-code-for-my-blog.aspx</link><pubDate>Fri, 09 Oct 2009 17:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9905492</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9905492.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9905492</wfw:commentRss><description>&lt;P&gt;It occurred to me this morning that while I previously shared some details on &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/09/12/expression-web-my-msdn-blog-and-now-team-foundation-server.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/09/12/expression-web-my-msdn-blog-and-now-team-foundation-server.aspx"&gt;how I manage my MSDN blog&lt;/A&gt;, I've never shared my method for formatting code for the Web.&lt;/P&gt;
&lt;P&gt;Actually, calling it "my method" is definitely a bit of a stretch. I certainly didn't come up with the approach but rather refined someone else's approach (and code) to suit my needs. The original credit goes to &lt;A href="http://blogs.msdn.com/delay" mce_href="http://blogs.msdn.com/delay"&gt;David Anson&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Prior to adopting David's approach, I previously copied code from Visual Studio, pasted it into Microsoft Word, then copied it again in Microsoft Word, and finally pasted into Expression Web. While this achieved the desired end result -- meaning, formatted code with color syntax highlighting -- it definitely was a little kludgey. First, the four-step process -- while not excessively tedious -- was definitely less than desirable, because it often meant I had to fire up Word for the sole purpose of formatting code (note that copy/paste from Visual Studio into Expression Web does not preserve the formatting). Second -- and more importantly -- the resulting HTML markup was just "crap" (sorry, I can't think of a more eloquent way to put that right now).&lt;/P&gt;
&lt;P&gt;When I started looking at approaches for improving the formatting of code for my blog, I found that there were numerous "solutions" out there. However, I knew what I really wanted was something that would produce a minimal amount of HTML markup (or at least a lot less HTML than Microsoft Word) and, preferably, something that generated semantic markup as well -- or at least &lt;EM&gt;reasonably&lt;/EM&gt; semantic markup.&lt;/P&gt;
&lt;P&gt;What I mean by semantic markup is that code should be wrapped in a &lt;CODE&gt;&amp;lt;code&amp;gt;&lt;/CODE&gt; tag -- as well as a &lt;CODE&gt;&amp;lt;pre&amp;gt;&lt;/CODE&gt; tag (in order to correctly display line breaks, indenting, etc.). To understand what I mean by semantic markup for code, consider the following example:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System;

&lt;SPAN style="COLOR: #0000ff"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Class1
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #0000ff"&gt;public&lt;/SPAN&gt; Class1()
    {
        &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; foo = &lt;SPAN style="COLOR: #a31515"&gt;"foo"&lt;/SPAN&gt;;
    }
}&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;In HTML markup, this is expressed as:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;div&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='codeBlock'&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#0000ff'&amp;gt;&lt;/SPAN&gt;using&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; System;

&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#0000ff'&amp;gt;&lt;/SPAN&gt;public&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#0000ff'&amp;gt;&lt;/SPAN&gt;class&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#2b91af'&amp;gt;&lt;/SPAN&gt;Class1
&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#0000ff'&amp;gt;&lt;/SPAN&gt;public&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; Class1()
    {
        &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#0000ff'&amp;gt;&lt;/SPAN&gt;string&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; foo = &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt;#a31515'&amp;gt;&lt;/SPAN&gt;"foo"&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;;
    }
}&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;The &lt;CODE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;div&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='codeBlock'&amp;gt; &lt;/SPAN&gt;&lt;/CODE&gt;element is used to constrain lengthy code blocks (i.e. show a vertical scrollbar when necessary) and also format code with a background color and border. &lt;/P&gt;
&lt;P&gt;Note that in the stricted sense, this isn't 100% semantic markup because the &lt;CODE&gt;&amp;lt;span&amp;gt;&lt;/CODE&gt; tags are used to apply presentational styles, namely the various font colors. Truly semantic markup for code would specify something more like this:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;div&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='codeBlock'&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='keyword'&amp;gt;&lt;/SPAN&gt;using&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; System;

&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='keyword'&amp;gt;&lt;/SPAN&gt;public&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='keyword'&amp;gt;&lt;/SPAN&gt;class&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="userType"&amp;gt;&lt;/SPAN&gt;Class1
&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='keyword'&amp;gt;&lt;/SPAN&gt;public&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; Class1()
    {
        &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='keyword'&amp;gt;&lt;/SPAN&gt;string&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; foo = &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;='string'&amp;gt;&lt;/SPAN&gt;"foo"&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;;
    }
}
&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;CSS rules could then be used to achieve the color syntax highlighting:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;.keyword
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #0000ff"&gt;#0000ff&lt;/SPAN&gt;;
}
&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;.string
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;:&lt;SPAN style="COLOR: #0000ff"&gt; #a31515&lt;/SPAN&gt;;
}
&lt;SPAN style="COLOR: #a31515"&gt;code&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;.userType
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: #ff0000"&gt;color&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #0000ff"&gt;#2b91af&lt;/SPAN&gt;;
}&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;Anyway, getting back to the real topic for this post...&lt;/P&gt;
&lt;P&gt;I really liked David's approach since a) it was simple (meaning I didn't need to spend much time understanding his code sample), and b) it leveraged Visual Studio to handle the bulk of the formatting work.&lt;/P&gt;
&lt;P&gt;However, there were a couple of "fixes" that I found I needed:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;David's original code sample produced errors when I used it from SQL Server Management Studio 2005 (note that SQL Server Management Studio uses the Visual Studio "shell", so one should expect this to work)&lt;/LI&gt;
&lt;LI&gt;David's code sample only inserted a &lt;CODE&gt;&amp;lt;pre&amp;gt;&lt;/CODE&gt; tag (and not the corresponding &lt;CODE&gt;&amp;lt;code&amp;gt;&lt;/CODE&gt; and &lt;CODE&gt;&amp;lt;div class="codeBlock"&amp;gt;&lt;/CODE&gt; tags that I also wanted)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I also wanted to eliminate extraneous &lt;CODE&gt;&amp;lt;span&amp;gt;&lt;/CODE&gt; tags for the default color (i.e. black).&lt;/P&gt;
&lt;P&gt;Note that -- at least to this point -- I haven't made any attempt to generate 100% semantic markup (by converting the &lt;CODE&gt;&lt;SPAN style="COLOR: #ff0000"&gt;style &lt;/SPAN&gt;&lt;/CODE&gt;attributes to corresponding CSS class names), because I think it would be somewhat brittle (i.e. dependent on the default color options in Visual Studio) and, honestly, not worth the effort.&lt;/P&gt;
&lt;P&gt;Here's the updated code that I now use for my Rtf2Html.exe utility:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;PRE&gt;&lt;CODE&gt;&lt;SPAN style="COLOR: #008000"&gt;// Original source:
// http://blogs.msdn.com/delay/archive/2008/03/13/
// blogging-code-samples-should-be-easy-free-convertclipboardrtftohtmltext-tool-and-source-code.aspx

&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Collections.Generic;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Drawing;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Text;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Windows.Forms;

&lt;SPAN style="COLOR: #008000"&gt;// Convert Visual Studio 2008 RTF clipboard format into HTML by replacing the
// clipboard contents with its HTML representation in text format suitable for
// pasting into a web page or blog.
// USE: Copy to clipboard in VS, run this app (no UI), paste converted text
// NOTE: This is NOT a general-purpose RTF-to-HTML converter! It works well
// enough on the simple input I've tried, but may break for other input.
// TODO: Convert into a real application with a notify icon and hotkey.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;namespace&lt;/SPAN&gt; ConvertClipboardRtfToHtmlText
{
    &lt;SPAN style="COLOR: #0000ff"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ConvertClipboardRtfToHtmlText
&lt;/SPAN&gt;    {
        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; colorTbl = &lt;SPAN style="COLOR: #a31515"&gt;"\\colortbl;"&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; colorFieldTag = &lt;SPAN style="COLOR: #a31515"&gt;"cf"&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; tabExpansion = &lt;SPAN style="COLOR: #a31515"&gt;"    "&lt;/SPAN&gt;;

        [System.Diagnostics.CodeAnalysis.&lt;SPAN style="COLOR: #2b91af"&gt;SuppressMessage&lt;/SPAN&gt;(
            &lt;SPAN style="COLOR: #a31515"&gt;"Microsoft.Maintainability"&lt;/SPAN&gt;,
            &lt;SPAN style="COLOR: #a31515"&gt;"CA1502:AvoidExcessiveComplexity"&lt;/SPAN&gt;)]
        [&lt;SPAN style="COLOR: #2b91af"&gt;STAThread&lt;/SPAN&gt;]
        &lt;SPAN style="COLOR: #0000ff"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; Main()
        {
            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;Clipboard&lt;/SPAN&gt;.ContainsText(&lt;SPAN style="COLOR: #2b91af"&gt;TextDataFormat&lt;/SPAN&gt;.Rtf))
            {
                &lt;SPAN style="COLOR: #008000"&gt;// Create color table, populate with default color
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;&amp;gt; colors = &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;&amp;gt;();
                &lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt; defaultColor = &lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;.FromArgb(0, 0, 0);
                colors.Add(defaultColor);

                &lt;SPAN style="COLOR: #0000ff"&gt;bool&lt;/SPAN&gt; insideSpan = &lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;;

                &lt;SPAN style="COLOR: #008000"&gt;// Get RTF
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; rtf = &lt;SPAN style="COLOR: #2b91af"&gt;Clipboard&lt;/SPAN&gt;.GetText(&lt;SPAN style="COLOR: #2b91af"&gt;TextDataFormat&lt;/SPAN&gt;.Rtf);

                &lt;SPAN style="COLOR: #008000"&gt;// Parse color table
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; i = rtf.IndexOf(
                    colorTbl,
                    &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.OrdinalIgnoreCase);

                &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (-1 != i)
                {
                    i += colorTbl.Length;

                    &lt;SPAN style="COLOR: #008000"&gt;// When copying from Visual Studio, we expect
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #008000"&gt;// "\\colortbl;\r\n". However when copying from SQL Server
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #008000"&gt;// Management Studio, we expect just "\\colortbl;".
&lt;/SPAN&gt;                    SkipOptionalText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\r\n"&lt;/SPAN&gt;);

                    &lt;SPAN style="COLOR: #0000ff"&gt;while&lt;/SPAN&gt; ((i &amp;lt; rtf.Length) &amp;amp;&amp;amp; (&lt;SPAN style="COLOR: #a31515"&gt;'}'&lt;/SPAN&gt; != rtf[i]))
                    {
                        &lt;SPAN style="COLOR: #008000"&gt;// Add color to color table
&lt;/SPAN&gt;                        SkipOptionalText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\r\n"&lt;/SPAN&gt;);
                        SkipExpectedText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\\red"&lt;/SPAN&gt;);
                        &lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt; red = (&lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt;)ParseNumericField(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i);
                        SkipExpectedText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\\green"&lt;/SPAN&gt;);
                        &lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt; green = (&lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt;)ParseNumericField(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i);
                        SkipExpectedText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\\blue"&lt;/SPAN&gt;);
                        &lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt; blue = (&lt;SPAN style="COLOR: #0000ff"&gt;byte&lt;/SPAN&gt;)ParseNumericField(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i);
                        colors.Add(&lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;.FromArgb(red, green, blue));
                        SkipOptionalText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;"\r\n"&lt;/SPAN&gt;);
                        SkipExpectedText(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #a31515"&gt;";"&lt;/SPAN&gt;);
                    }
                }
                &lt;SPAN style="COLOR: #0000ff"&gt;else
&lt;/SPAN&gt;                {
                    &lt;SPAN style="COLOR: #0000ff"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NotSupportedException&lt;/SPAN&gt;(
                        &lt;SPAN style="COLOR: #a31515"&gt;"Missing/unknown colorTbl."&lt;/SPAN&gt;);
                }

                &lt;SPAN style="COLOR: #008000"&gt;// Find start of text and parse
&lt;/SPAN&gt;                i = rtf.IndexOf(&lt;SPAN style="COLOR: #a31515"&gt;"\\fs"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.OrdinalIgnoreCase);
                &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (-1 != i)
                {
                    &lt;SPAN style="COLOR: #008000"&gt;// Skip font size tag
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #0000ff"&gt;while&lt;/SPAN&gt; ((i &amp;lt; rtf.Length) &amp;amp;&amp;amp; (&lt;SPAN style="COLOR: #a31515"&gt;' '&lt;/SPAN&gt; != rtf[i]))
                    {
                        i++;
                    }
                    i++;

                    &lt;SPAN style="COLOR: #008000"&gt;// Begin building HTML text
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #2b91af"&gt;StringBuilder&lt;/SPAN&gt; sb = &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;StringBuilder&lt;/SPAN&gt;();
                    sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;div class='codeBlock'&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;"&lt;/SPAN&gt;);
                    &lt;SPAN style="COLOR: #0000ff"&gt;while&lt;/SPAN&gt; (i &amp;lt; rtf.Length)
                    {
                        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #a31515"&gt;'\\'&lt;/SPAN&gt; == rtf[i])
                        {
                            &lt;SPAN style="COLOR: #008000"&gt;// Parse escape code
&lt;/SPAN&gt;                            i++;
                            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; ((i &amp;lt; rtf.Length) &amp;amp;&amp;amp;
                                ((&lt;SPAN style="COLOR: #a31515"&gt;'{'&lt;/SPAN&gt; == rtf[i])
                                    || (&lt;SPAN style="COLOR: #a31515"&gt;'}'&lt;/SPAN&gt; == rtf[i])
                                    || (&lt;SPAN style="COLOR: #a31515"&gt;'\\'&lt;/SPAN&gt; == rtf[i])))
                            {
                                &lt;SPAN style="COLOR: #008000"&gt;// Escaped '{' or '}' or '\'
&lt;/SPAN&gt;                                sb.Append(rtf[i]);
                            }
                            &lt;SPAN style="COLOR: #0000ff"&gt;else
&lt;/SPAN&gt;                            {
                                &lt;SPAN style="COLOR: #008000"&gt;// Parse tag
&lt;/SPAN&gt;                                &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; tagEnd = rtf.IndexOf(&lt;SPAN style="COLOR: #a31515"&gt;' '&lt;/SPAN&gt;, i);
                                &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (-1 != tagEnd)
                                {
                                    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (rtf.Substring(
                                        i,
                                        tagEnd - i).StartsWith(
                                            colorFieldTag,
                                            &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.OrdinalIgnoreCase))
                                    {
                                        &lt;SPAN style="COLOR: #008000"&gt;// Parse color field tag
&lt;/SPAN&gt;                                        i += colorFieldTag.Length;
                                        &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; colorIndex = ParseNumericField(rtf, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; i);
                                        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; ((colorIndex &amp;lt; 0)
                                            || (colors.Count &amp;lt;= colorIndex))
                                        {
                                            &lt;SPAN style="COLOR: #0000ff"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NotSupportedException&lt;/SPAN&gt;(
                                                &lt;SPAN style="COLOR: #a31515"&gt;"Bad color index."&lt;/SPAN&gt;);
                                        }

                                        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (insideSpan == &lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;)
                                        {
                                            sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;/span&amp;gt;"&lt;/SPAN&gt;);
                                            insideSpan = &lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;;
                                        }

                                        &lt;SPAN style="COLOR: #008000"&gt;// Change to new color
&lt;/SPAN&gt;                                        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (colors[colorIndex] != defaultColor)
                                        {
                                            sb.AppendFormat(
                                                &lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;span style='color:#{0:x2}{1:x2}{2:x2}'&amp;gt;"&lt;/SPAN&gt;,
                                                colors[colorIndex].R, colors[colorIndex].G,
                                                colors[colorIndex].B);

                                            insideSpan = &lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;;
                                        }
                                    }
                                    &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #a31515"&gt;"tab"&lt;/SPAN&gt; ==
                                        rtf.Substring(i, tagEnd - i))
                                    {
                                        sb.Append(tabExpansion);
                                    }

                                    &lt;SPAN style="COLOR: #008000"&gt;// Skip tag
&lt;/SPAN&gt;                                    i = tagEnd;
                                }
                                &lt;SPAN style="COLOR: #0000ff"&gt;else
&lt;/SPAN&gt;                                {
                                    &lt;SPAN style="COLOR: #0000ff"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NotSupportedException&lt;/SPAN&gt;(
                                        &lt;SPAN style="COLOR: #a31515"&gt;"Malformed tag."&lt;/SPAN&gt;);
                                }
                            }
                        }
                        &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #a31515"&gt;'}'&lt;/SPAN&gt; == rtf[i])
                        {
                            &lt;SPAN style="COLOR: #008000"&gt;// Terminal curly; done
&lt;/SPAN&gt;                            &lt;SPAN style="COLOR: #0000ff"&gt;break&lt;/SPAN&gt;;
                        }
                        &lt;SPAN style="COLOR: #0000ff"&gt;else
&lt;/SPAN&gt;                        {
                            &lt;SPAN style="COLOR: #008000"&gt;// Normal character; HTML-escape '&amp;lt;', '&amp;gt;', and '&amp;amp;'
&lt;/SPAN&gt;                            &lt;SPAN style="COLOR: #0000ff"&gt;switch&lt;/SPAN&gt; (rtf[i])
                            {
                                &lt;SPAN style="COLOR: #0000ff"&gt;case&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;'&amp;lt;'&lt;/SPAN&gt;:
                                    sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;lt;"&lt;/SPAN&gt;);
                                    &lt;SPAN style="COLOR: #0000ff"&gt;break&lt;/SPAN&gt;;
                                &lt;SPAN style="COLOR: #0000ff"&gt;case&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;'&amp;gt;'&lt;/SPAN&gt;:
                                    sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;gt;"&lt;/SPAN&gt;);
                                    &lt;SPAN style="COLOR: #0000ff"&gt;break&lt;/SPAN&gt;;
                                &lt;SPAN style="COLOR: #0000ff"&gt;case&lt;/SPAN&gt; &lt;SPAN style="COLOR: #a31515"&gt;'&amp;amp;'&lt;/SPAN&gt;:
                                    sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;amp;"&lt;/SPAN&gt;);
                                    &lt;SPAN style="COLOR: #0000ff"&gt;break&lt;/SPAN&gt;;
                                &lt;SPAN style="COLOR: #0000ff"&gt;default&lt;/SPAN&gt;:
                                    sb.Append(rtf[i]);
                                    &lt;SPAN style="COLOR: #0000ff"&gt;break&lt;/SPAN&gt;;
                            }
                        }
                        i++;
                    }

                    &lt;SPAN style="COLOR: #008000"&gt;// Finish building HTML text
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (insideSpan == &lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;)
                    {
                        sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;/span&amp;gt;"&lt;/SPAN&gt;);
                        insideSpan = &lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;;
                    }

                    sb.Append(&lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;"&lt;/SPAN&gt;);

                    &lt;SPAN style="COLOR: #008000"&gt;// Update the clipboard text
&lt;/SPAN&gt;                    &lt;SPAN style="COLOR: #2b91af"&gt;Clipboard&lt;/SPAN&gt;.SetText(sb.ToString());
                }
                &lt;SPAN style="COLOR: #0000ff"&gt;else
&lt;/SPAN&gt;                {
                    &lt;SPAN style="COLOR: #0000ff"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NotSupportedException&lt;/SPAN&gt;(
                        &lt;SPAN style="COLOR: #a31515"&gt;"Missing text section."&lt;/SPAN&gt;);
                }
            }
        }

        &lt;SPAN style="COLOR: #008000"&gt;// Skip the specified text
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; SkipExpectedText(&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; s, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; i, &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; text)
        {
            &lt;SPAN style="COLOR: #0000ff"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #0000ff"&gt;char&lt;/SPAN&gt; c &lt;SPAN style="COLOR: #0000ff"&gt;in&lt;/SPAN&gt; text)
            {
                &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; ((s.Length &amp;lt;= i) || (c != s[i]))
                {
                    &lt;SPAN style="COLOR: #0000ff"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NotSupportedException&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Expected text missing."&lt;/SPAN&gt;);
                }
                i++;
            }
        }

        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; SkipOptionalText(
            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; s,
            &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; i,
            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; text)
        {
            &lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; substring = s.Substring(i, text.Length);

            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt; (substring == text)
            {
                i += text.Length;
            }
        }

        &lt;SPAN style="COLOR: #008000"&gt;// Parse a numeric field
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; ParseNumericField(&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt; s, &lt;SPAN style="COLOR: #0000ff"&gt;ref&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; i)
        {
            &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; value = 0;
            &lt;SPAN style="COLOR: #0000ff"&gt;while&lt;/SPAN&gt; ((i &amp;lt; s.Length) &amp;amp;&amp;amp; &lt;SPAN style="COLOR: #0000ff"&gt;char&lt;/SPAN&gt;.IsDigit(s[i]))
            {
                value *= 10;
                value += s[i] - &lt;SPAN style="COLOR: #a31515"&gt;'0'&lt;/SPAN&gt;;
                i++;
            }
            &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; value;
        }
    }
}&lt;/CODE&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;I suppose I could have kept the ConvertClipboardRtfToHtmlText moniker that David originally had, but for some reason I decided to abbreviate it. In hindsight, I'm really not sure why I didn't keep the name, but oh well...&lt;/P&gt;
&lt;P&gt;Whenever I need a code sample in a blog post, I simply copy the code in Visual Studio, double-click Rtf2Html.exe in my &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx"&gt;Toolbox&lt;/A&gt;, and then paste into Expression Web. It's still a three-step process, but not one that takes more than three or four seconds, and more importantly, it now produces much better HTML markup than the hack I used to use with Microsoft Word.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9905492" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Simplify/default.aspx">Simplify</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Web+Development/default.aspx">Web Development</category></item><item><title>Comparing Source Code Branches</title><link>http://blogs.msdn.com/jjameson/archive/2009/09/16/comparing-source-code-branches.aspx</link><pubDate>Wed, 16 Sep 2009 15:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895837</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9895837.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9895837</wfw:commentRss><description>&lt;P&gt;During the more than three years I spent helping Agilent Technologies migrate their Internet site from their legacy, proprietary platform to Microsoft Office SharePoint Server (MOSS) 2007, we unfortunately never used Team Foundation Server (TFS). Instead, we used Visual SourceSafe (VSS) in combination with a &lt;A href="http://blogs.msdn.com/jjameson/archive/2008/04/01/tfs-lite-for-wss-v2.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2008/04/01/tfs-lite-for-wss-v2.aspx"&gt;"Work Items" list in SharePoint&lt;/A&gt; that I've described in previous posts.&lt;/P&gt;
&lt;P&gt;While I certainly prefer TFS over VSS, sometimes you simply have to concede that you can't have everything you would like on a customer project and move on to actually getting the work done.&lt;/P&gt;
&lt;P&gt;However, just because we used VSS doesn't mean we didn't follow good Software Configuration Management (SCM) principles. For example, as I've &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx"&gt;described in the past&lt;/A&gt;, I insist on using branching right from the start. Thus when I setup the Visual Studio solution for the Agilent project, I created a &lt;STRONG&gt;Main&lt;/STRONG&gt; branch and subsequently created branches for the various releases (e.g. &lt;STRONG&gt;v1.0&lt;/STRONG&gt;, &lt;STRONG&gt;v2.0&lt;/STRONG&gt;, and &lt;STRONG&gt;v3.0&lt;/STRONG&gt;).&lt;/P&gt;
&lt;P&gt;The particular branch that a developer uses would thus depend on whether the changes are for the next major release or a QFE (hotfix) for the version running in Production. For example, after deploying the &lt;A href="http://www.chem.agilent.com/en-US/Support" mce_href="http://www.chem.agilent.com/en-US/Support"&gt;Technical Support site&lt;/A&gt; (i.e. v2.0), we began working on the "General Site" (i.e. v3.0). [Note that in Agilent's terminology, the "General Site" essentially refers to everything outside of Technical Support, the Literature Library, and the Online Store (i.e. the "Buy" tab).]&lt;/P&gt;
&lt;P&gt;However, since we didn't create the &lt;STRONG&gt;v3.0&lt;/STRONG&gt; branch until shortly before the v3.0 release, all v3 ("General Site") development was initially done on the &lt;STRONG&gt;Main&lt;/STRONG&gt; branch -- just like v2 (Tech Support) development was initially done in &lt;STRONG&gt;Main&lt;/STRONG&gt; prior to creating the &lt;STRONG&gt;v2.0 &lt;/STRONG&gt;branch.&lt;/P&gt;
&lt;P&gt;This branching strategy works really well, regardless of which particular SCM system you actually use. The key thing to remember is that all of the changes should eventually make it into the &lt;STRONG&gt;Main&lt;/STRONG&gt; branch (since that branch will eventually be used to create another branch for the next major release).&lt;/P&gt;
&lt;P&gt;The problem with VSS is that while it certainly supports branching, the merging features, um...well, let's just say that they leave a lot to be desired ;-)&lt;/P&gt;
&lt;P&gt;Personally speaking, I've never felt comfortable using the out-of-the-box merging features in VSS, and instead always insisted on merging the changes from one branch to another manually. TFS is obviously years ahead of VSS in terms of branching and merging, but as I said before, sometimes you simply have to deal with what you've got.&lt;/P&gt;
&lt;P&gt;Fortunately, long before the Agilent project, I had previously created my own process that takes a great deal of the "pain" out of manually merging source code. Here is what I came up with.&lt;/P&gt;
&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx"&gt;Toolbox&lt;/A&gt;, I have two simple scripts: DiffBranches.cmd and CopyBranch.cmd.&lt;/P&gt;
&lt;P&gt;Here are the contents of DiffBranches.cmd:&lt;/P&gt;
&lt;DIV class=consoleBlock&gt;&lt;PRE&gt;&lt;SAMP&gt;@echo off

setlocal

REM set DIFFTOOL=Windiff.exe
set DIFFTOOL=C:\NotBackedUp\Public\Toolbox\DiffMerge\DiffMerge.exe

set BRANCH1=%1
set BRANCH2=%2

if ("%BRANCH1%") == ("") set BRANCH1=Main

if ("%BRANCH2%") == ("") set BRANCH2=v3.0

call CopyBranch.cmd "%BRANCH1%" "%BRANCH1%_tmp"

call CopyBranch.cmd "%BRANCH2%" "%BRANCH2%_tmp"

"%DIFFTOOL%" "%BRANCH1%_tmp" "%BRANCH2%_tmp"&lt;/SAMP&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;As you can see, there's not much to it. I simply make temporary copies of the two branches (i.e. by copying the branch folder into a new folder appended with "_tmp") and then use my "Diff Tool" to compare the two folders. Originally, I used WinDiff, but once I &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/24/diffmerge-a-better-differencing-tool.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/24/diffmerge-a-better-differencing-tool.aspx"&gt;discovered DiffMerge&lt;/A&gt;, I quickly switched to using it exclusively for all of my "diff'ing" activities.&lt;/P&gt;
&lt;P&gt;The real "magic" lies in CopyBranch.cmd:&lt;/P&gt;
&lt;DIV class=consoleBlock&gt;&lt;PRE&gt;&lt;SAMP&gt;@echo off

setlocal

set BRANCH1=%1
set BRANCH2=%2

if ("%BRANCH1%") == ("") set BRANCH1=Main

if ("%BRANCH2%") == ("") set BRANCH2="%BRANCH1%_tmp"

robocopy "%BRANCH1%" "%BRANCH2%" /E /MIR /XD bin obj TestResults /XF *.scc *.suo *.user *.vspscc
&lt;/SAMP&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;Note that I put the word &lt;EM&gt;magic&lt;/EM&gt; in quotes because it's really not magic at all. When copying a source code branch, I simply use robocopy.exe and specify the following options:&lt;/P&gt;
&lt;TABLE class=accent1 cellSpacing=0 class="accent1"&gt;
&lt;CAPTION&gt;robocoby.exe command-line options used in CopyBranch.cmd&lt;/CAPTION&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH&gt;Command-Line Option&lt;/TH&gt;
&lt;TH&gt;Comments&lt;/TH&gt;&lt;/TR&gt;&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;/E&lt;/TD&gt;
&lt;TD&gt;Copy subdirectories, including empty ones&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;/MIR&lt;/TD&gt;
&lt;TD&gt;Mirror the directory tree, thus ensuring that when I subsequently run CopyBranch.cmd, any deleted files from the original branch are removed from the "temporary" copy of the branch)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;/XD bin obj TestResults&lt;/TD&gt;
&lt;TD&gt;Exclude directories matching the given names/paths, thus skipping the compiled output (i.e. bin and obj) as well as the test results generated by running unit tests from within Visual Studio&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;/XF *.scc *.suo *.user *.vspscc &lt;/TD&gt;
&lt;TD&gt;Exclude files matching the given names/paths/wildcards, thus skipping source code control files (*.scc and *.vspscc), and Visual Studio solution/project user-specific options (i.e. *.suo and *.user)&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;For example, let's suppose that I've checked in some changes to the &lt;STRONG&gt;v3.0 &lt;/STRONG&gt;branch that need to be propagated to the &lt;STRONG&gt;Main &lt;/STRONG&gt;branch. I would open a command prompt and run the following:&lt;/P&gt;
&lt;DIV class=consoleBlock&gt;&lt;PRE&gt;&lt;SAMP&gt;C:\NotBackedUp\Agilent&amp;gt;DiffBranches.cmd v3.0 Main&lt;/SAMP&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;After the two branches are copied to their respective temporary folders, DiffMerge.exe is launched to compare the two branches. Since I exclude many of the directories and files that are &lt;EM&gt;expected&lt;/EM&gt; to differ between the two branches, I can quickly view only the differences that I am interested in. I can even use DiffMerge.exe to apply the changes interactively (checking out the files to be updated beforehand as necessary). This greatly reduces the effort involved in manually merging changes from one branch into another.&lt;/P&gt;
&lt;P&gt;Note that it takes a little bit of time to copy a branch the first time, but this is lightning fast on subsequent runs. Hence why I don't delete the "_tmp" folders after comparing two branches.&lt;/P&gt;
&lt;P&gt;I occasionally use this process even on projects where we've used Team Foundation Server. For example, I sometimes create a new workspace in TFS to represent a "temporary branch" where I want to experiment with some substantial changes to the source code (while I still have pending changes in my main workspace, that I may have shelved but don't want to check-in just yet). Using a little robocopy.exe and DiffMerge.exe, I can more easily compare two branches or workspaces.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895837" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/TFS/default.aspx">TFS</category></item><item><title>Best Practices for .NET Assembly Versioning</title><link>http://blogs.msdn.com/jjameson/archive/2009/04/03/best-practices-for-net-assembly-versioning.aspx</link><pubDate>Fri, 03 Apr 2009 15:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9530613</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9530613.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9530613</wfw:commentRss><description>&lt;P&gt;Whenever a new .NET assembly project is created in Visual Studio, a file named AssemblyInfo is created that contains attributes used to define the version of the assembly during compilation.&lt;/P&gt;
&lt;P&gt;Using assembly versions effectively enables various team members to identify deployed assemblies and helps troubleshoot problems that may occur in a particular environment (e.g. Development, Test, or Production).&lt;/P&gt;
&lt;P&gt;Assembly versions consist of four different parts ({Major Version}.{Minor Version}.{Build Number}.{Revision}):&lt;/P&gt;
&lt;DL&gt;
&lt;DT&gt;Major Version&lt;/DT&gt;
&lt;DD&gt;Manually incremented for major releases, such as adding many new features to the solution.&lt;/DD&gt;
&lt;DT&gt;Minor Version&lt;/DT&gt;
&lt;DD&gt;Manually incremented for minor releases, such as introducing small changes to existing features.&lt;/DD&gt;
&lt;DT&gt;Build Number&lt;/DT&gt;
&lt;DD&gt;Typically incremented automatically as part of every build performed on the Build Server. This allows each build to be tracked and tested.&lt;/DD&gt;
&lt;DT&gt;Revision&lt;/DT&gt;
&lt;DD&gt;Incremented for QFEs (a.k.a. “hotfixes” or patches) to builds released into the Production environment (PROD). This is set to zero for the initial release of any major/minor version of the solution.&lt;/DD&gt;&lt;/DL&gt;
&lt;P&gt;As a general guideline, it is best to use the same version number for all assemblies compiled as part of the solution. This is easily accomplished using &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx"&gt;linked files in Visual Studio solutions&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;When building the solution, there are two version numbers that need to be considered: the file version number and the .NET assembly version number.&lt;/P&gt;
&lt;H4&gt;File Version&lt;/H4&gt;
&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyfileversionattribute(VS.71).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyfileversionattribute(VS.71).aspx"&gt;AssemblyFileVersionAttribute&lt;/A&gt; should be incremented automatically as part of the build process. At the beginning of the build process, before the build label is applied in the source control system, the Build Number portion of the file version is incremented (or the Revision, if building a QFE).&lt;/P&gt;
&lt;P&gt;The file version should be isolated in its own file (e.g. AssemblyVersionInfo.cs) to easily automate the process of incrementing it with every build. This file can then be "linked into" each project in the solution, thus ensuring all of the various assemblies in the solution share the same file version for a particular build.&lt;/P&gt;
&lt;H4&gt;Assembly Version&lt;/H4&gt;
&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyversionattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyversionattribute.aspx"&gt;AssemblyVersionAttribute&lt;/A&gt; is the version that .NET uses when linking assemblies. This number is not incremented with every build to avoid having to specify binding redirects.&lt;/P&gt;
&lt;P&gt;Assembly versions are incremented manually when branching the code for a release (to the PROD environment).&lt;/P&gt;
&lt;P&gt;The assembly version number should be specified in a "shared assembly info" file (e.g. &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx"&gt;SharedAssemblyInfo.cs&lt;/A&gt;), thus ensuring that all of the various assemblies in the solution have the same assembly version.&lt;/P&gt;
&lt;P&gt;By default, the &lt;STRONG&gt;Product version&lt;/STRONG&gt; shown in the file properties window is the same as the value specified for &lt;STRONG&gt;AssemblyFileVersionAttribute&lt;/STRONG&gt;. Setting &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyinformationalversionattribute(VS.71).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyinformationalversionattribute(VS.71).aspx"&gt;AssemblyInformationalVersionAttribute&lt;/A&gt; to be the same as &lt;STRONG&gt;AssemblyVersionAttribute&lt;/STRONG&gt; ensures the &lt;STRONG&gt;Product version&lt;/STRONG&gt; shown in the file properties window matches the &lt;STRONG&gt;Version &lt;/STRONG&gt;displayed in the &lt;A href="http://msdn.microsoft.com/en-us/library/34149zk3.aspx" mce_href="http://msdn.microsoft.com/en-us/library/34149zk3.aspx"&gt;GAC shell extension&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9530613" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Shared Assembly Info in Visual Studio Projects</title><link>http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx</link><pubDate>Fri, 03 Apr 2009 15:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9530581</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9530581.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9530581</wfw:commentRss><description>&lt;P&gt;Yesterday I introduced the concept of &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx"&gt;linked files in Visual Studio solutions&lt;/A&gt; with a follow-up on my recommendation for &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/02/ca1704-code-analysis-warning-and-using-custom-dictionaries-in-visual-studio.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/02/ca1704-code-analysis-warning-and-using-custom-dictionaries-in-visual-studio.aspx"&gt;configuring a custom dictionary&lt;/A&gt; to eliminate CA1704 code analysis warnings.&lt;/P&gt;
&lt;P&gt;Another practical application of linked files is what I refer to as "shared assembly info" -- referring to the assembly attributes that should be the same across all projects in the solution, such as &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblycompanyattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblycompanyattribute.aspx"&gt;AssemblyCompanyAttribute&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;To implement this, create a file in the solution folder named SharedAssemblyInfo.cs and then add a link in each project to SharedAssemblyInfo.cs. You can also move the linked SharedAssemblyInfo.cs into the Properties folder so that it sits side-by-side with the AssemblyInfo.cs that is specific to each project in the solution, as shown below.&lt;/P&gt;
&lt;DIV class=image&gt;&lt;IMG title="" alt="" src="http://blogs.msdn.com/photos/jjameson/images/9529036/309x480.aspx" width=309 height=480 mce_src="http://blogs.msdn.com/photos/jjameson/images/9529036/309x480.aspx"&gt; 
&lt;DIV class=caption&gt;Figure 1: Linked SharedAssemblyInfo.cs files in a Visual Studio solution&lt;/DIV&gt;
&lt;DIV class=imageLink&gt;&lt;A href="http://blogs.msdn.com/photos/jjameson/images/9529036/original.aspx" target=_blank mce_href="http://blogs.msdn.com/photos/jjameson/images/9529036/original.aspx"&gt;See full-sized image.&lt;/A&gt; &lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;I recommend placing the following assembly attributes in SharedAssemblyInfo.cs (and, of course, removing them as necessary from the project-specific AssemblyInfo.cs files):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;AssemblyCompany&lt;/LI&gt;
&lt;LI&gt;AssemblyProduct&lt;/LI&gt;
&lt;LI&gt;AssemblyCopyright&lt;/LI&gt;
&lt;LI&gt;AssemblyTrademark&lt;/LI&gt;
&lt;LI&gt;AssemblyConfiguration&lt;/LI&gt;
&lt;LI&gt;AssemblyDescription&lt;/LI&gt;
&lt;LI&gt;CLSCompliant&lt;/LI&gt;
&lt;LI&gt;ComVisible&lt;/LI&gt;
&lt;LI&gt;AssemblyVersion&lt;/LI&gt;
&lt;LI&gt;AssemblyInformationalVersion&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The AssemblyInfo.cs files typically have the following assembly attributes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;AssemblyTitle&lt;/LI&gt;
&lt;LI&gt;AssemblyCulture&lt;/LI&gt;
&lt;LI&gt;Guid&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Here is a sample SharedAssemblyInfo.cs file:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Reflection;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Runtime.CompilerServices;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Runtime.InteropServices;

&lt;SPAN style="COLOR: #008000"&gt;// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyCompany&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Fabrikam Technologies"&lt;/SPAN&gt;)]
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyProduct&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Demo"&lt;/SPAN&gt;)]
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyCopyright&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Copyright ? Fabrikam Technologies 2009"&lt;/SPAN&gt;)]
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyTrademark&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;)]

&lt;SPAN style="COLOR: #008000"&gt;// Make it easy to distinguish Debug and Release (i.e. Retail) builds;
// for example, through the file properties window.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;#if&lt;/SPAN&gt; DEBUG
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyConfiguration&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Debug"&lt;/SPAN&gt;)]
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyDescription&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Flavor=Debug"&lt;/SPAN&gt;)] &lt;SPAN style="COLOR: #008000"&gt;// a.k.a. "Comments"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;#else
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #808080"&gt;[assembly: AssemblyConfiguration("Retail")]
[assembly: AssemblyDescription("Flavor=Retail")] // a.k.a. "Comments"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;#endif

&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;CLSCompliant&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;)]

&lt;SPAN style="COLOR: #008000"&gt;// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;ComVisible&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;)]

&lt;SPAN style="COLOR: #008000"&gt;// Note that the assembly version does not get incremented for every build
// to avoid problems with assembly binding (or requiring a policy or
// &amp;lt;bindingRedirect&amp;gt; in the config file).
//
// The AssemblyFileVersionAttribute is incremented with every build in order
// to distinguish one build from another. AssemblyFileVersion is specified
// in AssemblyVersionInfo.cs so that it can be easily incremented by the
// automated build process.
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyVersion&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"1.0.0.0"&lt;/SPAN&gt;)]

&lt;SPAN style="COLOR: #008000"&gt;// By default, the "Product version" shown in the file properties window is
// the same as the value specified for AssemblyFileVersionAttribute.
// Set AssemblyInformationalVersionAttribute to be the same as
// AssemblyVersionAttribute so that the "Product version" in the file
// properties window matches the version displayed in the GAC shell extension.
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyInformationalVersion&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"1.0.0.0"&lt;/SPAN&gt;)] &lt;SPAN style="COLOR: #008000"&gt;// a.k.a. "Product version"&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;Note how the &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyconfigurationattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblyconfigurationattribute.aspx"&gt;AssemblyConfigurationAttribute&lt;/A&gt; and &lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblydescriptionattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.assemblydescriptionattribute.aspx"&gt;AssemblyDescriptionAttribute&lt;/A&gt; are set based on conditional compilation constants (in order to easily distinguish Debug and Release builds).&lt;/P&gt;
&lt;P&gt;Here is a sample AssemblyInfo.cs file:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Reflection;
&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt; System.Runtime.InteropServices;

&lt;SPAN style="COLOR: #008000"&gt;// Note: Shared assembly information is specified in SharedAssemblyInfo.cs

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyTitle&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"Fabrikam.Demo.CoreServices"&lt;/SPAN&gt;)]
[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;AssemblyCulture&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;)]

&lt;SPAN style="COLOR: #008000"&gt;// The following GUID is for the ID of the typelib if this project is exposed to COM
&lt;/SPAN&gt;[&lt;SPAN style="COLOR: #0000ff"&gt;assembly&lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Guid&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"88d50bdd-34bc-414a-98d6-6fefe701d41b"&lt;/SPAN&gt;)]&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/03/best-practices-for-net-assembly-versioning.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/03/best-practices-for-net-assembly-versioning.aspx"&gt;next post&lt;/A&gt;, I'll discuss assembly versioning in more detail.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9530581" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>CA1704 Code Analysis Warning and Using Custom Dictionaries in Visual Studio</title><link>http://blogs.msdn.com/jjameson/archive/2009/04/02/ca1704-code-analysis-warning-and-using-custom-dictionaries-in-visual-studio.aspx</link><pubDate>Thu, 02 Apr 2009 17:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9529175</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9529175.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9529175</wfw:commentRss><description>&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx"&gt;previous post&lt;/A&gt;, I introduced the concept of linking files in Visual Studio solutions.&lt;/P&gt;
&lt;P&gt;A good use of this feature is specifying a custom dictionary for your solution.&lt;/P&gt;
&lt;P&gt;Once you enable Code Analysis on your projects, you are likely to encounter warnings similar to the following:&lt;/P&gt;
&lt;BLOCKQUOTE class=directQuote&gt;MSBUILD : warning : CA1704 : Microsoft.Naming : Correct the spelling of 'Fabrikam' in namespace name 'Fabrikam.Demo.CoreServices.Logging'. &lt;/BLOCKQUOTE&gt;
&lt;P&gt;If you right-click one of these warnings and then click &lt;STRONG&gt;Show Error Help&lt;/STRONG&gt;, you will find the following:&lt;/P&gt;
&lt;BLOCKQUOTE class=directQuote&gt;
&lt;P&gt;&lt;STRONG&gt;How to Fix Violations&lt;/STRONG&gt;&lt;BR&gt;To fix a violation of this rule, correct the spelling of the word or add the word to a custom dictionary named CustomDictionary.xml. Place the dictionary in the installation directory of the tool, the project directory, or in the directory associated with the tool under the user's profile (%USERPROFILE%\Application Data\...). &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;DIV class=reference&gt;&lt;CITE&gt;Identifiers should be spelled correctly&lt;/CITE&gt; 
&lt;DIV class=referenceLink&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/bb264492.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb264492.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb264492.aspx&lt;/A&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;However, I don't recommend using any of these options. Here's why...&lt;/P&gt;
&lt;P&gt;We want our custom dictionary to be applied to all projects in our solution -- not just one project. This would make us tend to believe that the first or last option described above would be the best choice. However, we also want our custom dictionary to be easily updated by any developer on the team, and -- as always -- we also want to keep things as simple as possible.&lt;/P&gt;
&lt;P&gt;Forcing each developer on your team to copy the CustomDictionary.xml file into some folder -- and subsequently manage updates to this file on his or her local development environment -- is certainly less than ideal.&lt;/P&gt;
&lt;P&gt;Therefore, the best place to put CustomDictionary.xml is in source control right alongside the solution file. Thus when any developer "gets latest" on the solution, he or she will automatically get the latest custom dictionary. This also ensures that new team members get everything they need on the first "get" from source control.&lt;/P&gt;
&lt;P&gt;So, now that we know we want CustomDictionary.xml stored side-by-side with the Visual Studio solution file, the only thing left to do is configure Visual Studio to use our custom dictionary for each project in the solution.&lt;/P&gt;
&lt;P&gt;This is accomplished by adding a link in each project to CustomDictionary.xml (in the solution folder) and subsequently configuring the following property on the linked file:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Build Action: &lt;STRONG&gt;CodeAnalysisDictionary&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Now you can simply add items to the CustomDictionary.xml for the solution, as shown below, and eliminate those CA1704 warnings.&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;?&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;xml&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;version&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt;1.0&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;encoding&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt;utf-8&lt;/SPAN&gt;"&lt;SPAN style="COLOR: #0000ff"&gt; ?&amp;gt;
&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Dictionary&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Words&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Recognized&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
      &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Word&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;Fabrikam&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Word&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Recognized&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Words&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Dictionary&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;Since the file is in source control, you can obviously track changes to the file and view the history at any point in the future.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9529175" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Linked Files in Visual Studio Solutions</title><link>http://blogs.msdn.com/jjameson/archive/2009/04/02/linked-files-in-visual-studio-solutions.aspx</link><pubDate>Thu, 02 Apr 2009 16:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9529100</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9529100.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9529100</wfw:commentRss><description>&lt;P&gt;A couple of years ago, I wrote a post introducing my system for &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx"&gt;structuring Visual Studio solutions&lt;/A&gt;. However, I apparently forgot to post a follow-up providing additional details, such as configuring assembly versioning and what I like to call "shared assembly information."&lt;/P&gt;
&lt;P&gt;Before I can cover these details, I need to first ensure that you are familiar with the concept of linking files in Visual Studio solutions, why this is a powerful feature, and when to use it.&lt;/P&gt;
&lt;P&gt;If you ever used Visual SourceSafe (VSS), you likely used its feature for sharing files across multiple projects. For example, you could check-in a file at the root of your solution, and then drag-and-drop it into other projects (i.e. "subfolders") in your solution. Thus, whenever a change was made to the file (regardless of which particular VSS project the change was made in), the next time you "got latest" the change would be reflected in all locations. This was a common way of, for example, having all of your .NET assemblies in the same Visual Studio solution specify the same assembly version.&lt;/P&gt;
&lt;P&gt;Note that Team Foundation Server (TFS) does not provide an equivalent "share file" feature. Fortunately, however, you no longer need such a feature.&lt;/P&gt;
&lt;P&gt;Back in the days of the original Visual Studio .NET and the following version, Visual Studio .NET 2003, whenever you added an existing file to a project, it copied the file into the corresponding location in the project.&lt;/P&gt;
&lt;P&gt;However, in Visual Studio 2005, the &lt;STRONG&gt;Add Existing Item&lt;/STRONG&gt; feature provided the ability to choose to either &lt;STRONG&gt;Add&lt;/STRONG&gt; the item or &lt;STRONG&gt;Add As Link &lt;/STRONG&gt;(via the little down arrow on the button in the dialog box).&lt;/P&gt;
&lt;P&gt;In other words, once you upgraded to Visual Studio 2005, it was no longer necessary to rely on any "sharing" features of your source control system in order to have multiple projects always reference the latest version of a file.&lt;/P&gt;
&lt;P&gt;Note that when you &lt;STRONG&gt;Add &lt;/STRONG&gt;an item in Visual Studio 2005 or Visual Studio 2008, the behavior is the same as earlier versions (meaning the file is copied into the corresponding location within the project). When you choose to &lt;STRONG&gt;Add As Link&lt;/STRONG&gt;, however, you simply reference the file in-place. [Don't worry, relative paths ensure that everyone on your team is free to choose whatever root folder they wish for their individual workspaces.]&lt;/P&gt;
&lt;P&gt;To illustrate this concept, I quickly built out a "demo" solution, as shown below. &lt;/P&gt;
&lt;DIV class=image&gt;&lt;IMG title="" alt="" src="http://blogs.msdn.com/photos/jjameson/images/9529036/309x480.aspx" width=309 height=480 mce_src="http://blogs.msdn.com/photos/jjameson/images/9529036/309x480.aspx"&gt; 
&lt;DIV class=caption&gt;Figure 1: Linked files in a Visual Studio solution&lt;/DIV&gt;
&lt;DIV class=imageLink&gt;&lt;A href="http://blogs.msdn.com/photos/jjameson/images/9529036/original.aspx" target=_blank mce_href="http://blogs.msdn.com/photos/jjameson/images/9529036/original.aspx"&gt;See full-sized image.&lt;/A&gt; &lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;The corresponding folder structure on disk resembles the following:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Fabrikam 
&lt;UL&gt;
&lt;LI&gt;Demo 
&lt;UL&gt;
&lt;LI&gt;Dev &lt;EM&gt;(branch)&lt;/EM&gt; 
&lt;UL&gt;
&lt;LI&gt;Lab1 &lt;EM&gt;(branch) &lt;/EM&gt;
&lt;UL&gt;
&lt;LI&gt;AssemblyVersionInfo.cs&lt;/LI&gt;
&lt;LI&gt;CustomDictionary.xml&lt;/LI&gt;
&lt;LI&gt;Fabrikam.Demo.sln&lt;/LI&gt;
&lt;LI&gt;Fabrikam.Demo.snk&lt;/LI&gt;
&lt;LI&gt;SharedAssemblyInfo.cs&lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;AdminConsole 
&lt;UL&gt;
&lt;LI&gt;AdminConsole.csproj&lt;/LI&gt;
&lt;LI&gt;Program.cs&lt;/LI&gt;
&lt;LI&gt;Properties 
&lt;UL&gt;
&lt;LI&gt;AssemblyInfo.cs&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;CoreServices 
&lt;UL&gt;
&lt;LI&gt;CoreServices.csproj&lt;/LI&gt;
&lt;LI&gt;Logging 
&lt;UL&gt;
&lt;LI&gt;Logger.cs&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Properties 
&lt;UL&gt;
&lt;LI&gt;AssemblyInfo.cs&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Note that &lt;STRONG&gt;AssemblyVersionInfo.cs&lt;/STRONG&gt;, &lt;STRONG&gt;CustomDictionary.xml&lt;/STRONG&gt;, &lt;STRONG&gt;Fabrikam.Demo.snk&lt;/STRONG&gt;, and &lt;STRONG&gt;SharedAssemblyInfo.cs &lt;/STRONG&gt;reside in the same folder as the Visual Studio solution file and are subsequently "linked into" the two Visual C# projects. Thus whenever a change is made to one of these files, the next build of each project will reflect that change.&lt;/P&gt;
&lt;P&gt;With this foundation in place, I'll explain some other recommended best practices over a series of follow-up posts, including:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/02/ca1704-code-analysis-warning-and-using-custom-dictionaries-in-visual-studio.aspx"&gt;Using custom dictionaries in Visual Studio&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/03/shared-assembly-info-in-visual-studio-projects.aspx"&gt;Shared assembly info in Visual Studio projects&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/jjameson/archive/2009/04/03/best-practices-for-net-assembly-versioning.aspx"&gt;Best practices for .NET assembly versioning&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Stay tuned!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9529100" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/TFS/default.aspx">TFS</category></item><item><title>DiffMerge - A Better Differencing Tool</title><link>http://blogs.msdn.com/jjameson/archive/2009/03/24/diffmerge-a-better-differencing-tool.aspx</link><pubDate>Tue, 24 Mar 2009 17:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9504266</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9504266.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9504266</wfw:commentRss><description>&lt;P&gt;Last summer, I added &lt;A href="http://www.sourcegear.com/diffmerge/" mce_href="http://www.sourcegear.com/diffmerge/"&gt;DiffMerge&lt;/A&gt; to my &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/03/22/backedup-and-notbackedup.aspx"&gt;Toolbox&lt;/A&gt; and I haven't used WinDiff since.&lt;/P&gt;
&lt;P&gt;DiffMerge can do everything WinDiff can, plus a whole lot more -- like intra-line highlighting, merging, and comparing files using configurable rulesets (although you'll likely never need any more than those that come "out-of-the-box" with DiffMerge).&lt;/P&gt;
&lt;P&gt;And since the folks at SourceGear don't mind giving away DiffMerge for free, there's no reason &lt;EM&gt;not&lt;/EM&gt; to use it!&lt;/P&gt;
&lt;P&gt;Heck, I even configure Visual Studio to use DiffMerge as my comparison tool instead of the default tool that comes with Team Foundation Server (TFS).&lt;/P&gt;
&lt;P&gt;To customize your TFS comparison tool in Visual Studio 2008:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;On the &lt;STRONG&gt;Tools&lt;/STRONG&gt; menu, click &lt;STRONG&gt;Options...&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Options&lt;/STRONG&gt; window, expand &lt;STRONG&gt;Source Control&lt;/STRONG&gt;, select &lt;STRONG&gt;Visual Studio Team Foundation Server&lt;/STRONG&gt;, and then click &lt;STRONG&gt;Configure User Tools...&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Configure User Tools&lt;/STRONG&gt; window, click the Add... or Modify... button as necessary to configure the following:&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Extension: &lt;STRONG&gt;.*&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Operation: &lt;STRONG&gt;Compare&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Command: &lt;STRONG&gt;C:\NotBackedUp\Public\Toolbox\DiffMerge\DiffMerge.exe&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Arguments: &lt;STRONG&gt;%1 %2&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Obviously, you may need to adjust the path to &lt;STRONG&gt;DiffMerge.exe &lt;/STRONG&gt;as necessary for your environment.&lt;/P&gt;
&lt;P&gt;In the past, I tried other tools like BeyondCompare -- but I preferred the simplicity of WinDiff. Then, a couple of years ago, one of my peers pointed me to an internal tool called "Odd" that would do intra-line highlighting. However, I couldn't get over the fact that this was an internal tool only -- and thus not something I could recommend to customers.&lt;/P&gt;
&lt;P&gt;When I stumbled across DiffMerge, I was delighted and I haven't looked back since.&lt;/P&gt;
&lt;P&gt;Perhaps Visual Studio 2010 will ship with a vastly improved differencing tool, but in the meantime -- or just in case it doesn't -- DiffMerge is my tool of choice.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9504266" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/My+System/default.aspx">My System</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/TFS/default.aspx">TFS</category></item><item><title>Visual Studio Macro for Collapsing All Items in Solution Explorer</title><link>http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macro-for-collapsing-all-items-in-solution-explorer.aspx</link><pubDate>Wed, 11 Mar 2009 17:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9470541</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9470541.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9470541</wfw:commentRss><description>&lt;P&gt;Along with &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macros-for-unloading-reloading-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macros-for-unloading-reloading-projects.aspx"&gt;my Visual Studio macros for unloading/reloading projects in a solution&lt;/A&gt;, another macro that I use just as much, if not more frequently, is my &lt;CODE&gt;CollapseAllItems()&lt;/CODE&gt; macro:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;Public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; CollapseAllItems()
    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionExplorer &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Window = _
        DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)

    solutionExplorer.Activate()&lt;SPAN style="COLOR: #0000ff"&gt;
&lt;/SPAN&gt;
    DTE.SuppressUI = &lt;SPAN style="COLOR: #0000ff"&gt;True

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy = solutionExplorer.Object

        &lt;SPAN style="COLOR: #0000ff"&gt;For&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Each&lt;/SPAN&gt; item &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchyItem _
            &lt;SPAN style="COLOR: #0000ff"&gt;In&lt;/SPAN&gt; solutionHierarchy.UIHierarchyItems

            CollapseItem(item, solutionHierarchy)
        &lt;SPAN style="COLOR: #0000ff"&gt;Next
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Catch&lt;/SPAN&gt; ex &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Exception
        WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Error collapsing all items: "&lt;/SPAN&gt; _
            &amp;amp; ex.Message)

    &lt;SPAN style="COLOR: #0000ff"&gt;Finally
&lt;/SPAN&gt;        DTE.SuppressUI = &lt;SPAN style="COLOR: #0000ff"&gt;False
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Try
End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;The &lt;CODE&gt;CollapseItem()&lt;/CODE&gt; method is used to recursively collapse each item in the hierarchy:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; CollapseItem( _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; item &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchyItem, _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy)

    &lt;SPAN style="COLOR: #0000ff"&gt;For&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Each&lt;/SPAN&gt; child &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchyItem &lt;SPAN style="COLOR: #0000ff"&gt;In&lt;/SPAN&gt; item.UIHierarchyItems
        CollapseItem(child, solutionHierarchy)

        &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (item.UIHierarchyItems.Expanded = &lt;SPAN style="COLOR: #0000ff"&gt;True&lt;/SPAN&gt;) &lt;SPAN style="COLOR: #0000ff"&gt;Then
&lt;/SPAN&gt;            WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Collapsing item ("&lt;/SPAN&gt; &amp;amp; item.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")..."&lt;/SPAN&gt;)
            item.UIHierarchyItems.Expanded = &lt;SPAN style="COLOR: #0000ff"&gt;False

&lt;/SPAN&gt;            &lt;SPAN style="COLOR: #008000"&gt;' HACK: Known bug in Visual Studio 2005
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: #008000"&gt;' http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=114597
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (item.UIHierarchyItems.Expanded = &lt;SPAN style="COLOR: #0000ff"&gt;True&lt;/SPAN&gt;) &lt;SPAN style="COLOR: #0000ff"&gt;Then
&lt;/SPAN&gt;                item.Select(vsUISelectionType.vsUISelectionTypeSelect)
                solutionHierarchy.DoDefaultAction()
            &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Next
End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;While it is great that Visual Studio "synchronizes" the &lt;STRONG&gt;Solution Explorer&lt;/STRONG&gt; window to show the current file in the solution hierarchy, in large Visual Studio solutions, things can get a bit bewildering at times if many of the projects are expanded down to the level of individual files.&lt;/P&gt;
&lt;P&gt;Perhaps in a future version of Visual Studio, we'll have the ability to right-click the solution in &lt;STRONG&gt;Solution Explorer&lt;/STRONG&gt; and then click something like &lt;STRONG&gt;Collapse All&lt;/STRONG&gt;. Until then, I don't see me giving up my dependency on this macro anytime soon.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9470541" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Visual Studio Macros for Unloading/Reloading Projects</title><link>http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macros-for-unloading-reloading-projects.aspx</link><pubDate>Wed, 11 Mar 2009 16:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9470483</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9470483.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9470483</wfw:commentRss><description>&lt;P&gt;As promised in a &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/06/large-visual-studio-solutions-by-loading-unloading-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/06/large-visual-studio-solutions-by-loading-unloading-projects.aspx"&gt;post&lt;/A&gt; last week, here are the macros that I use to quickly unload or reload dozens of projects in a large Visual Studio solution. Hmmm, perhaps &lt;EM&gt;effortlessly&lt;/EM&gt; is a better word choice -- considering I might need to wait 30 seconds or so for all of the projects to unload or reload.&lt;/P&gt;
&lt;P&gt;Here is my &lt;CODE&gt;UnloadAllProjects()&lt;/CODE&gt; macro:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;Public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; UnloadAllProjects()
    &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (DTE.Solution &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt; _
        &lt;SPAN style="COLOR: #0000ff"&gt;Or&lt;/SPAN&gt; DTE.Solution.Count = 0) &lt;SPAN style="COLOR: #0000ff"&gt;Then

&lt;/SPAN&gt;        MessageBox.Show( _
            &lt;SPAN style="COLOR: #a31515"&gt;"Cannot unload all projects because no solution is open."&lt;/SPAN&gt;, _
            &lt;SPAN style="COLOR: #a31515"&gt;"Error"&lt;/SPAN&gt;, _
            MessageBoxButtons.OK, _
            MessageBoxIcon.Error)

        &lt;SPAN style="COLOR: #0000ff"&gt;Exit&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionName &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = _
        DTE.Solution.Properties.Item(&lt;SPAN style="COLOR: #a31515"&gt;"Name"&lt;/SPAN&gt;).Value.ToString()

    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Unloading projects in solution ("&lt;/SPAN&gt; &amp;amp; solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")..."&lt;/SPAN&gt;)

    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionExplorer &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Window = _
        DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)

    solutionExplorer.Activate()&lt;SPAN style="COLOR: #0000ff"&gt;
&lt;/SPAN&gt;
    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy = solutionExplorer.Object

    &lt;SPAN style="COLOR: #0000ff"&gt;For&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Each&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Project &lt;SPAN style="COLOR: #0000ff"&gt;In&lt;/SPAN&gt; DTE.Solution.Projects
        &lt;SPAN style="COLOR: #008000"&gt;' Note that the project may be a solution folder, in which case we
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' want to unload all of the projects within the solution folder.
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;'
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' Also note if the project is already unloaded, or is a solution
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' folder containing no projects -- then a COM exception occurs.
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;            UnloadProject(proj, solutionName, solutionHierarchy)
        &lt;SPAN style="COLOR: #0000ff"&gt;Catch&lt;/SPAN&gt; ex &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Exception
            WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Error unloading project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"): "&lt;/SPAN&gt; _
                &amp;amp; ex.Message)

        &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Next

&lt;/SPAN&gt;    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Successfully unloaded projects in solution ("&lt;/SPAN&gt; _
                &amp;amp; solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")."&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;The actual work of unloading a project is delegated to the &lt;CODE&gt;UnloadProject()&lt;/CODE&gt; method:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; UnloadProject( _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Project, _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; solutionName &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt;, _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy)

    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;Not&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt;)
    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt;.IsNullOrEmpty(solutionName) = &lt;SPAN style="COLOR: #0000ff"&gt;False&lt;/SPAN&gt;)
    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;Not&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt;)

    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Unloading project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")..."&lt;/SPAN&gt;)

    &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (proj.Kind = Constants.vsProjectKindMisc) &lt;SPAN style="COLOR: #0000ff"&gt;Then
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' "Miscellaenous Files" cannot be unloaded
&lt;/SPAN&gt;        WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;") cannot be unloaded."&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: #0000ff"&gt;Return
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; projPath &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\"&lt;/SPAN&gt; &amp;amp; proj.Name

    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; obj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Object&lt;/SPAN&gt; = solutionHierarchy.GetItem(projPath)
    obj.Select(vsUISelectionType.vsUISelectionTypeSelect)

    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; projectName &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = proj.Name
    DTE.ExecuteCommand(&lt;SPAN style="COLOR: #a31515"&gt;"Project.UnloadProject"&lt;/SPAN&gt;)
    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Successfully unloaded project ("&lt;/SPAN&gt; &amp;amp; projectName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")."&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;A few interesting notes...&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I originally used the &lt;STRONG&gt;Record TemporaryMacro&lt;/STRONG&gt; feature in Visual Studio a few years ago to determine how projects are loaded and unloaded. This led me to the scantily documented &lt;CODE&gt;DTE.ExecuteCommand(&lt;SPAN style="COLOR: #a31515"&gt;"Project.UnloadProject"&lt;/SPAN&gt;)&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;I discovered that a specific project type ("Miscellaneous Files") will always throw a COM exception whenever you try to unload or reload it. Consequently, I skip that one altogether.&lt;/LI&gt;
&lt;LI&gt;While I tried to find a way to determine if a particular project (or projects within a solution folder) are already unloaded -- and thus avoid a COM exception when subsequently attempting to unload it again -- I ended up punting this and instead simply wrapping the "unload" operation in a try/catch block.&lt;/LI&gt;
&lt;LI&gt;The &lt;CODE&gt;WriteOutput()&lt;/CODE&gt; method is provided in &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/11/tracing-and-logging-from-visual-studio-macros.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/11/tracing-and-logging-from-visual-studio-macros.aspx"&gt;a previous post&lt;/A&gt;.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If you take the above code and essentially search-and-replace "unload" with "reload" then you will end up with my macro to reload all projects within the solution:&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;Public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; ReloadAllProjects()
    &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (DTE.Solution &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt; _
        &lt;SPAN style="COLOR: #0000ff"&gt;Or&lt;/SPAN&gt; DTE.Solution.Count = 0) &lt;SPAN style="COLOR: #0000ff"&gt;Then

&lt;/SPAN&gt;        MessageBox.Show( _
            &lt;SPAN style="COLOR: #a31515"&gt;"Cannot reload all projects because no solution is open."&lt;/SPAN&gt;, _
            &lt;SPAN style="COLOR: #a31515"&gt;"Error"&lt;/SPAN&gt;, _
            MessageBoxButtons.OK, _
            MessageBoxIcon.Error)

        &lt;SPAN style="COLOR: #0000ff"&gt;Exit&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionName &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = _
        DTE.Solution.Properties.Item(&lt;SPAN style="COLOR: #a31515"&gt;"Name"&lt;/SPAN&gt;).Value.ToString()

    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Reloading projects in solution ("&lt;/SPAN&gt; &amp;amp; solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")..."&lt;/SPAN&gt;)

    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionExplorer &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Window = _
        DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)

    solutionExplorer.Activate()&lt;SPAN style="COLOR: #0000ff"&gt;
&lt;/SPAN&gt;
    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy = solutionExplorer.Object

    &lt;SPAN style="COLOR: #0000ff"&gt;For&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Each&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Project &lt;SPAN style="COLOR: #0000ff"&gt;In&lt;/SPAN&gt; DTE.Solution.Projects
        &lt;SPAN style="COLOR: #008000"&gt;' Note that the project may be a solution folder, in which case we
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' want to reload all of the projects within the solution folder.
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;'
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' Also note if the project is already loaded, or is a solution
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' folder containing no projects -- then a COM exception occurs.
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;            ReloadProject(proj, solutionName, solutionHierarchy)
        &lt;SPAN style="COLOR: #0000ff"&gt;Catch&lt;/SPAN&gt; ex &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Exception
            WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Error reloading project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"): "&lt;/SPAN&gt; _
                &amp;amp; ex.Message)

        &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Next

&lt;/SPAN&gt;    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Successfully reloaded projects in solution ("&lt;/SPAN&gt; _
                &amp;amp; solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")."&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub

Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; ReloadProject( _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Project, _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; solutionName &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt;, _
    &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; UIHierarchy)

    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;Not&lt;/SPAN&gt; proj &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt;)
    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt;.IsNullOrEmpty(solutionName) = &lt;SPAN style="COLOR: #0000ff"&gt;False&lt;/SPAN&gt;)
    Debug.Assert(&lt;SPAN style="COLOR: #0000ff"&gt;Not&lt;/SPAN&gt; solutionHierarchy &lt;SPAN style="COLOR: #0000ff"&gt;Is&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Nothing&lt;/SPAN&gt;)

    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Reloading project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")..."&lt;/SPAN&gt;)

    &lt;SPAN style="COLOR: #0000ff"&gt;If&lt;/SPAN&gt; (proj.Kind = Constants.vsProjectKindMisc) &lt;SPAN style="COLOR: #0000ff"&gt;Then
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #008000"&gt;' "Miscellaenous Files" cannot be unloaded
&lt;/SPAN&gt;        WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;") cannot be unloaded."&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: #0000ff"&gt;Return
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;If

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; projPath &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = solutionName &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\"&lt;/SPAN&gt; &amp;amp; proj.Name

    &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; obj &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Object&lt;/SPAN&gt; = solutionHierarchy.GetItem(projPath)
    obj.Select(vsUISelectionType.vsUISelectionTypeSelect)

    DTE.ExecuteCommand(&lt;SPAN style="COLOR: #a31515"&gt;"Project.ReloadProject"&lt;/SPAN&gt;)
    WriteOutput(&lt;SPAN style="COLOR: #a31515"&gt;"Successfully reloaded project ("&lt;/SPAN&gt; &amp;amp; proj.Name &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;")."&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;Like I mentioned earlier, unloading or reloading all of the projects within a solution is not exactly an instantaneous operation. However, when you consider the incremental build time saved by unloading all of the projects in a large solution except for the few you are working on at any given time, you definitely come out far ahead in the end. You'll be amazed at how much more productive you can be when your solution containing 50+ projects incrementally builds in just a few seconds when all but a handful of the projects are unloaded.&lt;/P&gt;
&lt;P&gt;I hope you find these macros as helpful as I have over the years.&lt;/P&gt;
&lt;P&gt;Perhaps in a future version of Visual Studio, we'll have the ability to right-click the solution in &lt;STRONG&gt;Solution Explorer&lt;/STRONG&gt; and then click something like &lt;STRONG&gt;Unload Projects in Solution&lt;/STRONG&gt; (similar to the &lt;STRONG&gt;Unload Projects in Solution Folder&lt;/STRONG&gt; option that is currently available -- but only for solution folders, not the solution itself). Until then, I don't see me giving up my dependency on these macros anytime soon.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9470483" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Tracing and Logging from Visual Studio Macros</title><link>http://blogs.msdn.com/jjameson/archive/2009/03/11/tracing-and-logging-from-visual-studio-macros.aspx</link><pubDate>Wed, 11 Mar 2009 15:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9470451</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9470451.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9470451</wfw:commentRss><description>&lt;P&gt;As I mentioned in a &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/06/large-visual-studio-solutions-by-loading-unloading-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/06/large-visual-studio-solutions-by-loading-unloading-projects.aspx"&gt;post&lt;/A&gt; last week, I often use macros in Visual Studio to automate development tasks.&lt;/P&gt;
&lt;P&gt;Before sharing some of my most frequently used macros, however, I wanted to first introduce the method I use to trace events and log messages while running various macros.&lt;/P&gt;
&lt;P&gt;Take a look at the following &lt;STRONG&gt;Output &lt;/STRONG&gt;window from Visual Studio. Notice how there is an item in the &lt;STRONG&gt;Show output from &lt;/STRONG&gt;dropdown list titled &lt;STRONG&gt;Macros &lt;/STRONG&gt;(a.k.a. "the macro output pane").&lt;/P&gt;
&lt;DIV class=image&gt;&lt;IMG title="" height=199 alt="" src="http://blogs.msdn.com/photos/jjameson/images/9470423/500x199.aspx" width=500 mce_src="http://blogs.msdn.com/photos/jjameson/images/9470423/500x199.aspx"&gt; 
&lt;DIV class=caption&gt;Figure 1: Macro output pane&lt;/DIV&gt;
&lt;DIV class=imageLink&gt;&lt;A href="http://blogs.msdn.com/photos/jjameson/images/9470423/original.aspx" target=_blank mce_href="http://blogs.msdn.com/photos/jjameson/images/9470423/original.aspx"&gt;See full-sized image.&lt;/A&gt; &lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;Chances are that when you look at your Visual Studio environment, you won't see this item. So, why does it appear in my environment?&lt;/P&gt;
&lt;P&gt;The macro output pane is actually created on-the-fly, as necessary, whenever I run one of my macros that implements tracing (i.e. writes output). This is done via the &lt;CODE&gt;GetMacroOutputPane()&lt;/CODE&gt; function, as shown below.&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Function&lt;/SPAN&gt; GetMacroOutputPane() &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; OutputWindowPane
        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; ow &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; OutputWindow = _
            DTE.Windows.Item(Constants.vsWindowKindOutput).Object()

        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; outputPane &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; OutputWindowPane

        &lt;SPAN style="COLOR: #0000ff"&gt;Try
&lt;/SPAN&gt;            outputPane = ow.OutputWindowPanes.Item(&lt;SPAN style="COLOR: #a31515"&gt;"Macros"&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: #0000ff"&gt;Catch&lt;/SPAN&gt; ex &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; Exception
            outputPane = ow.OutputWindowPanes.Add(&lt;SPAN style="COLOR: #a31515"&gt;"Macros"&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Try

&lt;/SPAN&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;Return&lt;/SPAN&gt; outputPane
    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Function&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;
&lt;P&gt;Pretty simple, eh? If the macro output pane exists, then use it; otherwise add a new pane.&lt;/P&gt;
&lt;P&gt;In order to simplify writing output messages -- as well as timestamp each message as it is written -- I use the &lt;CODE&gt;WriteOutput()&lt;/CODE&gt; method&lt;/P&gt;
&lt;DIV class=codeBlock&gt;&lt;CODE&gt;&lt;PRE&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt; WriteOutput( _
        &lt;SPAN style="COLOR: #0000ff"&gt;ByVal&lt;/SPAN&gt; s &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt;)

        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; buffer &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; StringBuilder = &lt;SPAN style="COLOR: #0000ff"&gt;New&lt;/SPAN&gt; StringBuilder

        buffer.Append(&lt;SPAN style="COLOR: #0000ff"&gt;Date&lt;/SPAN&gt;.Now.ToLongTimeString())
        buffer.Append(&lt;SPAN style="COLOR: #a31515"&gt;" "&lt;/SPAN&gt;)
        buffer.Append(s)
        buffer.Append(vbCrLf)

        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; output &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;String&lt;/SPAN&gt; = buffer.ToString()

        &lt;SPAN style="COLOR: #0000ff"&gt;Dim&lt;/SPAN&gt; outputPane &lt;SPAN style="COLOR: #0000ff"&gt;As&lt;/SPAN&gt; OutputWindowPane = GetMacroOutputPane()
        outputPane.OutputString(output)
    &lt;SPAN style="COLOR: #0000ff"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/CODE&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9470451" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Large Visual Studio Solutions and Loading/Unloading Projects</title><link>http://blogs.msdn.com/jjameson/archive/2009/03/06/large-visual-studio-solutions-by-loading-unloading-projects.aspx</link><pubDate>Fri, 06 Mar 2009 18:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9462793</guid><dc:creator>Jeremy Jameson</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jjameson/comments/9462793.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jjameson/commentrss.aspx?PostID=9462793</wfw:commentRss><description>&lt;P&gt;As I noted in my &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/06/why-i-m-not-a-fan-of-wspbuilder.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/06/why-i-m-not-a-fan-of-wspbuilder.aspx"&gt;previous post&lt;/A&gt;, I typically work with "large" Visual Studio solutions. Note that I put this in quotes, because the definition of "large" will likely vary widely based on your individual experience. Note that I'm not referring to "large" like the source for the .NET Framework itself, but rather "large" like most enterprise customers that I typically engage with. If you want a number, then let's say somewhere in the range of 50-75 projects in a single Visual Studio solution.&lt;/P&gt;
&lt;P&gt;On my previous project, we had 52 projects in our solution. On my current project, there are 30.&lt;/P&gt;
&lt;P&gt;You may very well have more or less, but the following concepts and tips should still apply. If you are on a development team with several hundred projects, then either you are a member of the NetFx team or you more than likely already know about what I'm about to tell you in this post ;-)&lt;/P&gt;
&lt;P&gt;If you work with multiple Visual Studio solutions that only have a handful of projects, but this is simply because your team decided to break up one big solution into several smaller ones, then this post is intended especially for you.&lt;/P&gt;
&lt;P&gt;As you start adding more and more projects to a solution, you'll inevitably discover the following to be true:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Load time increases (i.e. the time it takes to start Visual Studio and open your solution)&lt;/LI&gt;
&lt;LI&gt;Incremental build time increases, even when the only changes that have been made are in "leaf" projects (i.e. projects that don't reference other projects)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Obviously we should expect the build time to take a while whenever we make a change in one project that is referenced by many others (e.g. &lt;A href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2007/04/18/structure-visual-studio-solutions.aspx"&gt;a "CoreServices" project&lt;/A&gt; like I've described in the past).&lt;/P&gt;
&lt;P&gt;If, like me, you've grown accustomed to Test Driven Development (TDD) however, then you know that it's essential to minimize the &lt;A href="http://msdn.microsoft.com/en-us/library/aa730844(VS.80).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa730844(VS.80).aspx"&gt;"Red, Green, Refactor"&lt;/A&gt; cycle. If your &lt;A href="http://blogs.msdn.com/jjameson/archive/2009/03/06/why-i-m-not-a-fan-of-wspbuilder.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/06/why-i-m-not-a-fan-of-wspbuilder.aspx"&gt;incremental build time requires 28 seconds&lt;/A&gt;, then your developer productivity is going to take a hit in a big, big way.&lt;/P&gt;
&lt;P&gt;So, what can we do to mitigate these issues?&lt;/P&gt;
&lt;P&gt;One approach is to create multiple Visual Studio solutions with a subset of projects. Developers could then open the specific solution (or, possibly, &lt;EM&gt;solutions&lt;/EM&gt; -- plural) containing a subset of the projects they need to work on at any given time.&lt;/P&gt;
&lt;P&gt;I really don't like -- or obviously recommend -- this approach, because it can be very problematic (for example, having to synchronize changes to the build configuration). Even worse, though, is that depending on how you partition your solution, you may end up having to switch from project references to file references for assembly dependencies. Anyone who has ever used file references for their own code should tell you that this is something to avoid.&lt;/P&gt;
&lt;P&gt;Note that the recommendation to use a single, "master" solution is nothing new. We've had this prescriptive guidance out for a number of years now (please forgive the fact that MSDN still refers to using Visual SourceSafe instead of Team Foundation Server in &lt;A href="http://msdn.microsoft.com/en-us/library/ms998208.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms998208.aspx"&gt;this article&lt;/A&gt; -- there may very well be an updated article that I simply haven't bothered to take the time and find).&lt;/P&gt;
&lt;P&gt;Unfortunately, what was fundamentally missing from the original prescriptive guidance was any mention of the feature in Visual Studio that allows you to effectively work with a solution containing numerous projects. This has become critical in light of the shift to TDD.&lt;/P&gt;
&lt;P&gt;If you right-click a project in Visual Studio, you'll see the &lt;STRONG&gt;Unload Project&lt;/STRONG&gt; option way down near the bottom of the context menu. When you unload a project, Visual Studio completely ignores the project (and all of the items in the project). Unloaded projects are not compiled when you press &lt;KEY&gt;CTRL+SHIFT+B&lt;/KEY&gt;, which can substantially reduce your incremental build time, thereby making you a much more productive TDD developer! You will also find the time required to open the solution can be greatly reduced by unloading projects.&lt;/P&gt;
&lt;P&gt;Whenever you need to change something in an unloaded project, simply right-click the project and click &lt;STRONG&gt;Reload Project&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;Unloading a project is also useful whenever you need to edit the MSBuild file -- for example, to &lt;A href="http://blogs.msdn.com/jjameson/archive/2008/04/10/a-better-way-to-build-sharepoint-solution-packages-and-cab-files.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2008/04/10/a-better-way-to-build-sharepoint-solution-packages-and-cab-files.aspx"&gt;rebuild a CAB or WSP whenever a dependency changes&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;An important thing to understand about loading and unloading projects is that the settings are stored in the solutions options (.suo) file which is specific to each developer and should never be stored in source control. In other words, if I unload a project in my workspace, this has no effect on other team members. Removing a project, on the other hand, changes the solution file (.sln) itself and therefore impacts other members of the development team.&lt;/P&gt;
&lt;P&gt;Note that you can quickly unload or reload multiple projects at a time by using solution folders within Visual Studio. If you right-click a solution folder, you will see the option to &lt;STRONG&gt;Unload Projects in Solution Folder&lt;/STRONG&gt;. I typically structure my Visual Studio solutions in a hierarchical fashion (i.e. nested solution folders) to make it very easy to load or unload various "subsystems" or features.&lt;/P&gt;
&lt;P&gt;Also note that you can use Visual Studio macros to quickly unload or reload all of the projects in a solution with a single click (well, actually a double-click, but you get the point).&lt;/P&gt;
&lt;P&gt;I'll share the macros that I developed and have been using for years in &lt;A class="" href="http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macros-for-unloading-reloading-projects.aspx" mce_href="http://blogs.msdn.com/jjameson/archive/2009/03/11/visual-studio-macros-for-unloading-reloading-projects.aspx"&gt;a separate post&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;There is one caveat that you should be aware of when unloading projects. Visual Studio warns you when you attempt to unload projects with pending changes in source control. Generally speaking, you want to avoid proceeding whenever Visual Studio displays the warning for this scenario.&lt;/P&gt;
&lt;P&gt;Note that modified files in unloaded projects are still shown in the &lt;STRONG&gt;Pending Changes&lt;/STRONG&gt; window when using TFS as the source code control provider. However, this isn't true for all providers (e.g. Visual SourceSafe).&lt;/P&gt;
&lt;P&gt;I've been using the loading/unloading project feature since my old Visual C++ 4.2 days, but -- at least based on my experience -- there seem to be a number of developers who are unaware of this great feature in Visual Studio. If I recall correctly, this was missing in the original Visual Studio.NET but, thankfully, was added back in a subsequent version, either Visual Studio .NET 2003 or Visual Studio 2005 (honestly, it's been too long to remember). Perhaps that the reason why the original prescriptive guidance on MSDN makes no mention of unloading/loading projects. Thank goodness it's back!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9462793" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jjameson/archive/tags/MOSS+2007/default.aspx">MOSS 2007</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Core+Development/default.aspx">Core Development</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/WSS+v3/default.aspx">WSS v3</category><category domain="http://blogs.msdn.com/jjameson/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item></channel></rss>