<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6152905331119398238</id><updated>2011-11-27T19:42:35.575-05:00</updated><category term='visual studio'/><category term='c#'/><category term='xml'/><category term='internationalization'/><category term='continuous integration'/><category term='tfs'/><category term='team build'/><category term='debugging'/><category term='process'/><category term='starting a project'/><category term='opc'/><category term='project management'/><category term='projectGuid'/><category term='WPF'/><category term='vb'/><title type='text'>Fowl Coder</title><subtitle type='html'>Coding, ranting about coding and other odds and ends.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-4280579743627772688</id><published>2009-08-04T12:15:00.003-04:00</published><updated>2009-08-04T12:24:53.956-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Constructors for VB.NET Modules</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/Snhgsb9RS4I/AAAAAAAAAI0/IiTW88iPFZs/s1600-h/Backhoe.jpg"&gt;&lt;img style="cursor: pointer; width: 134px; height: 134px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/Snhgsb9RS4I/AAAAAAAAAI0/IiTW88iPFZs/s400/Backhoe.jpg" alt="" id="BLOGGER_PHOTO_ID_5366145272547199874" border="0" /&gt;&lt;/a&gt; &lt;br /&gt;Did you know that you can have a constructor on a module?  I first got the notion to try this after thinking about static constructors in C#.  In C#, you can do something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;class Class1&lt;br /&gt;  {&lt;br /&gt;      private static int _magicNumber;&lt;br /&gt;&lt;br /&gt;      static Class1()&lt;br /&gt;      {&lt;br /&gt;          _magicNumber = 4;&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;So the next thing to try was to test this out in VB.NET:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;Module Module1&lt;br /&gt;&lt;br /&gt;Sub New()&lt;br /&gt;   Debug.WriteLine("New")&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public Sub Test()&lt;br /&gt;   Debug.WriteLine("Test")&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public Sub Test2()&lt;br /&gt;   Debug.WriteLine("Test2")&lt;br /&gt;End Sub&lt;br /&gt;End Module&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Running this and calling the methods Test / Test2 (in that order) yields this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;New&lt;br /&gt;Test&lt;br /&gt;Test2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So as you might expect, the construct only gets called once, but is called before any members are accessed in the module.  Handy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-4280579743627772688?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/4280579743627772688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=4280579743627772688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/4280579743627772688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/4280579743627772688'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/08/constructors-for-vbnet-modules.html' title='Constructors for VB.NET Modules'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/Snhgsb9RS4I/AAAAAAAAAI0/IiTW88iPFZs/s72-c/Backhoe.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-2639598077799006592</id><published>2009-06-30T14:07:00.005-04:00</published><updated>2009-06-30T14:32:11.885-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='team build'/><title type='text'>Gettinginto MSBuild / TFS Build</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9-lF1fc5euc/SkpZctbodCI/AAAAAAAAAGc/Ox5LOjG1hwQ/s1600-h/BuildBunny.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 175px;" src="http://3.bp.blogspot.com/_9-lF1fc5euc/SkpZctbodCI/AAAAAAAAAGc/Ox5LOjG1hwQ/s200/BuildBunny.jpg" alt="" id="BLOGGER_PHOTO_ID_5353189456849957922" border="0" /&gt;&lt;/a&gt;As you will no doubt agree, it's handy as heck to be able to get a fresh installer for your app on demand.  Right now our build is a relatively manual process that takes a number of hours to complete.  It's inefficient and error prone.  The answer - &lt;a href="http://fowlcoder.blogspot.com/2008/12/automation.html"&gt;automation&lt;/a&gt; of course!&lt;br /&gt;&lt;br /&gt;I've already set up our environment so that it will &lt;a href="http://fowlcoder.blogspot.com/2008/12/tfs-team-build.html"&gt;automatically build&lt;/a&gt; our code whenever somebody checks in - this is a good thing.  However, we're thinking about moving to the next step and getting our installer to be automatically built.  We're not sure exactly how we're going to do this yet, but the components are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Our .NET solution (most of our code is here).&lt;/li&gt;&lt;li&gt;Some VB 6 code (just enough here to have to make the build interesting).&lt;/li&gt;&lt;li&gt;An InstallShield installer (and dealing with the InstallShield licensing nonsense).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Our main options are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create our own MSBuild setup with custom tasks.  Getting this to happen on our build server would be ideal because then anyone on the team could make an installer through the TFS build interface.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Write a .NET app from scratch.  Not quite as slick as using MSBuild (considering MSBuild was sort of designed to do just this sort of thing), but I'll take whatever works.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Just to keep track of the resources, here are some of the pages I'm looking at:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.magenic.com/blogs/daniels/archive/2008/08/27/Implementing-VB6-on-TFS.aspx"&gt;This&lt;/a&gt; deals with incorporating VB6 and MSBuild&lt;/li&gt;&lt;li&gt;&lt;a href="http://peterblomqvist.blogspot.com/2007/10/linkmania-howto-create-custom-build.html"&gt;This&lt;/a&gt; has some links for creating custom build steps&lt;/li&gt;&lt;li&gt;&lt;a href="http://mark-dot-net.blogspot.com/2008/09/getting-started-with-msbuild.html"&gt;This&lt;/a&gt; is getting started with MSBuild&lt;/li&gt;&lt;/ul&gt;We need to check in some files, so here are some links for that:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/148867/how-do-i-move-a-tfs-file-with-c-api"&gt;This&lt;/a&gt; is some basic info for automating the TFS Version Control.&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/jmanning/archive/2006/08/08/692281.aspx"&gt;Creating a label&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;More to come as we narrow down the solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-2639598077799006592?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/2639598077799006592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=2639598077799006592' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2639598077799006592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2639598077799006592'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/06/gettinginto-msbuild-tfs-build.html' title='Gettinginto MSBuild / TFS Build'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9-lF1fc5euc/SkpZctbodCI/AAAAAAAAAGc/Ox5LOjG1hwQ/s72-c/BuildBunny.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-6349444331033715879</id><published>2009-05-10T21:31:00.005-04:00</published><updated>2009-05-10T21:44:59.506-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opc'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>OPC at RVNUG: The code and the slides</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9-lF1fc5euc/SgeCMmD81XI/AAAAAAAAAGI/C9BsfAfKvWY/s1600-h/cardboard_box.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 182px;" src="http://4.bp.blogspot.com/_9-lF1fc5euc/SgeCMmD81XI/AAAAAAAAAGI/C9BsfAfKvWY/s200/cardboard_box.jpg" alt="" id="BLOGGER_PHOTO_ID_5334375436530799986" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;First things first: Here is the &lt;a href="http://sites.google.com/site/fowlcoder/Home/OPCNUG.zip?attredirects=0"&gt;code&lt;/a&gt; and here are the &lt;a href="http://sites.google.com/site/fowlcoder/Home/OPC.pptx?attredirects=0"&gt;slides&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Thanks to everyone who attended (and participated in) my resent presentation on the &lt;a href="http://en.wikipedia.org/wiki/Open_Packaging_Convention"&gt;Open Packaging Convention (OPC) &lt;/a&gt;at the &lt;a href="http://www.rvnug.org/"&gt;Roanoke Valley .NET User Group (RVNUG)&lt;/a&gt;.  It was a rowdy group (my favorite kind) and it was a blast.&lt;br /&gt;&lt;br /&gt;Besides coming up with various connotations for the words 'Package', 'Parts' and 'Stream', we discussed some handy ways to use OPC:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Exporting / backing up data&lt;/li&gt;&lt;li&gt;Storing a gallery of images with additional metadata (geocoding, timestamp information,etc)&lt;/li&gt;&lt;li&gt;Grouping together log files.  This application seemed to generate the most interest.&lt;/li&gt;&lt;/ul&gt;OPC is a dirt simple way to store data in one place without needing a database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-6349444331033715879?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/6349444331033715879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=6349444331033715879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/6349444331033715879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/6349444331033715879'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/05/first-things-first-here-is-code-and.html' title='OPC at RVNUG: The code and the slides'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9-lF1fc5euc/SgeCMmD81XI/AAAAAAAAAGI/C9BsfAfKvWY/s72-c/cardboard_box.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-2834657661313789638</id><published>2009-04-20T12:08:00.002-04:00</published><updated>2009-04-20T12:22:59.800-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>DebuggerStepThroughAttribute</title><content type='html'>Let's say you have some code that often throws an exception, but you just swallow it and carry on.  This is usually fine, unless you have your debugger set to break on.  So take some code like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;Public Shared ReadOnly Property IsInstalled() As Boolean&lt;br /&gt; Get&lt;br /&gt;    Dim isInstalled As Boolean = False&lt;br /&gt;&lt;br /&gt;    Try&lt;br /&gt;       Dim temp as Object = CreateObject("Some.ActiveX")&lt;br /&gt;       isInstalled = True&lt;br /&gt;    Catch ex as Exception&lt;br /&gt;    End Try&lt;br /&gt;  &lt;br /&gt;    Return isInstalled&lt;br /&gt;&lt;br /&gt; End Get&lt;br /&gt;End Property&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If the COM object doesn't create properly, it will generate an exception.  This sort of code is usually in the start up of an application, so you might have to hit this every time you debug your app.  It's annoying. &lt;br /&gt;&lt;br /&gt;However, if you add the handy attribute &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerstepthroughattribute.aspx"&gt;DebuggerStepThrough&lt;/a&gt; just before the Get clause:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Public Shared ReadOnly Property IsInstalled() As Boolean&lt;br /&gt;   &amp;lt;DebuggerStepThrough()&amp;gt; _&lt;br /&gt;   Get&lt;br /&gt;      Dim isInstalled As Boolean = False&lt;br /&gt;&lt;br /&gt;      Try&lt;br /&gt;         Dim temp as Object = CreateObject(&amp;quot;Some.ActiveX&amp;quot;)&lt;br /&gt;         isInstalled = True&lt;br /&gt;      Catch ex as Exception&lt;br /&gt;      End Try&lt;br /&gt;      &lt;br /&gt;      Return isInstalled&lt;br /&gt;&lt;br /&gt;   End Get&lt;br /&gt;End Property&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Then Visual Studio just runs over the code like nothing ever happened.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-2834657661313789638?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/2834657661313789638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=2834657661313789638' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2834657661313789638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2834657661313789638'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/04/debuggerstepthroughattribute.html' title='DebuggerStepThroughAttribute'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-8096496283855247677</id><published>2009-04-18T21:38:00.000-04:00</published><updated>2009-04-18T22:55:22.976-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb'/><category scheme='http://www.blogger.com/atom/ns#' term='opc'/><title type='text'>Roanoke Code Camp 2009 - The Code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.rvnug.org/codecamp.aspx"&gt;&lt;img style="cursor: pointer; width: 400px; height: 80px;" src="http://3.bp.blogspot.com/_9-lF1fc5euc/ScGic44cA4I/AAAAAAAAAF4/iLsEOd4CAqM/s400/codecamp2009header.jpg" alt="" id="BLOGGER_PHOTO_ID_5314707652463035266" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Apologies for not getting this published sooner... Between getting ready to move houses and my normal level of laziness and procrastination, I haven't done it.  It also took some Googling to figure out &lt;a href="http://formatmysourcecode.blogspot.com/"&gt;how to include code in a BlogSpot post&lt;/a&gt;.  Enough &lt;a href="http://www.thefreedictionary.com/whinging"&gt;whinging&lt;/a&gt;, here's the code for the OPC (&lt;a href="httphttp://en.wikipedia.org/wiki/Open_Packaging_Convention"&gt;Open Packaging Convention&lt;/a&gt;) class I did.&lt;br /&gt;&lt;br /&gt;By the way, here is my &lt;a href="http://www.devx.com/dotnet/Article/41235"&gt;DevX article&lt;/a&gt; on the same subject that got published recently.&lt;br /&gt;&lt;br /&gt;Here is the code to create a package:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;'Open the package&lt;br /&gt;      Using package As Package = package.Open("c:\Example.zip", IO.FileMode.OpenOrCreate)&lt;br /&gt;&lt;br /&gt;          'Create the uri for the text file&lt;br /&gt;          Dim uri As New Uri("/TextFiles/MyTextFile.Text", UriKind.RelativeOrAbsolute)&lt;br /&gt;&lt;br /&gt;          'Create the part for the text file&lt;br /&gt;          Dim part As PackagePart = package.CreatePart(uri, System.Net.Mime.MediaTypeNames.Text.Plain)&lt;br /&gt;&lt;br /&gt;          'Get the stream for the part&lt;br /&gt;          Using stream As Stream = part.GetStream()&lt;br /&gt;&lt;br /&gt;              'This is the text we'll put in the part&lt;br /&gt;              Dim myText As String = "This is an ugly picture of a flower - Roanoke!"&lt;br /&gt;&lt;br /&gt;              'We need to get the string into a byte array to make it easy to write to the part stream&lt;br /&gt;              Dim buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(myText)&lt;br /&gt;&lt;br /&gt;              'Write to the part stream&lt;br /&gt;              stream.Write(buffer, 0, buffer.Length)&lt;br /&gt;&lt;br /&gt;          End Using&lt;br /&gt;&lt;br /&gt;          'This is the uri for the flower&lt;br /&gt;          Dim uri2 As New Uri("/Images/Flower.jpg", UriKind.RelativeOrAbsolute)&lt;br /&gt;&lt;br /&gt;          'Create the part for the image&lt;br /&gt;          Dim part2 As PackagePart = package.CreatePart(uri2, _&lt;br /&gt;                                                        System.Net.Mime.MediaTypeNames.Image.Jpeg)&lt;br /&gt;&lt;br /&gt;          'Get the stream for this part&lt;br /&gt;          Using stream As Stream = part2.GetStream()&lt;br /&gt;&lt;br /&gt;              'Read the data from the file&lt;br /&gt;              Dim buffer As Byte() = File.ReadAllBytes("c:\Flower.jpg")&lt;br /&gt;&lt;br /&gt;              'write the data to the part&lt;br /&gt;              stream.Write(buffer, 0, buffer.Length)&lt;br /&gt;&lt;br /&gt;          End Using&lt;br /&gt;&lt;br /&gt;          'Create a relationship between the parts&lt;br /&gt;          Dim relationship As PackageRelationship = _&lt;br /&gt;             part2.CreateRelationship(part.Uri, TargetMode.Internal, "flower_to_text")&lt;br /&gt;&lt;br /&gt;      End Using&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And here is the code to read that package:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt; 'Create the package&lt;br /&gt;       Using package As Package = package.Open("c:\Example.zip", IO.FileMode.Open)&lt;br /&gt;&lt;br /&gt;           'We know the Uri for the flower, so let's start there&lt;br /&gt;           Dim flowerUri As New Uri("/Images/Flower.jpg", UriKind.RelativeOrAbsolute)&lt;br /&gt;&lt;br /&gt;           'Get the part using the uri we just set up&lt;br /&gt;           Dim flowerPackagePart As PackagePart = _&lt;br /&gt;               package.GetPart(flowerUri)&lt;br /&gt;&lt;br /&gt;           'Create a relationship from the&lt;br /&gt;           Dim relationships As PackageRelationshipCollection = _&lt;br /&gt;              flowerPackagePart.GetRelationshipsByType("flower_to_text")&lt;br /&gt;&lt;br /&gt;           'Get the first relationship (in real code, we would want some error checking here)&lt;br /&gt;           Dim relationship As PackageRelationship = _&lt;br /&gt;               relationships(0)&lt;br /&gt;&lt;br /&gt;           'Get the part from the relationship (once again, this would need some&lt;br /&gt;           ' error protection because in a real world app this part might not exist anymore).&lt;br /&gt;           Dim textPart As PackagePart = package.GetPart(relationship.TargetUri)&lt;br /&gt;&lt;br /&gt;           'Get the stream&lt;br /&gt;           Using stream As Stream = textPart.GetStream()&lt;br /&gt;&lt;br /&gt;               'Create a buffer&lt;br /&gt;               Dim buffer(stream.Length) As Byte&lt;br /&gt;&lt;br /&gt;               'Read the stream&lt;br /&gt;               stream.Read(buffer, 0, stream.Length)&lt;br /&gt;&lt;br /&gt;               'Read the text&lt;br /&gt;               Dim myText As String = System.Text.ASCIIEncoding.ASCII.GetString(buffer)&lt;br /&gt;&lt;br /&gt;               'Show the text (the crowd should go wild here)&lt;br /&gt;               MessageBox.Show(myText)&lt;br /&gt;&lt;br /&gt;           End Using&lt;br /&gt;&lt;br /&gt;       End Using&lt;br /&gt;&lt;br /&gt;   End Sub&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-8096496283855247677?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/8096496283855247677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=8096496283855247677' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8096496283855247677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8096496283855247677'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/04/roanoke-code-camp-2009-code.html' title='Roanoke Code Camp 2009 - The Code'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9-lF1fc5euc/ScGic44cA4I/AAAAAAAAAF4/iLsEOd4CAqM/s72-c/codecamp2009header.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-8164799609195910434</id><published>2009-03-18T21:10:00.006-04:00</published><updated>2009-03-18T21:34:29.080-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><title type='text'>WPF Designer causes Visual Studio to Close</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9-lF1fc5euc/ScGdWBazT7I/AAAAAAAAAFw/_s0ARewos2g/s1600-h/VisualStudio.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 60px;" src="http://3.bp.blogspot.com/_9-lF1fc5euc/ScGdWBazT7I/AAAAAAAAAFw/_s0ARewos2g/s200/VisualStudio.png" alt="" id="BLOGGER_PHOTO_ID_5314702036937428914" border="0" /&gt;&lt;/a&gt;Okay, so we all know that the &lt;a href="http://msdn.microsoft.com/en-us/library/bb514656.aspx"&gt;WPF designer&lt;/a&gt; in &lt;a href="http://msdn.microsoft.com/en-us/vstudio/default.aspx"&gt;Visual Studio 2008&lt;/a&gt; is suboptimal.  And if you didn't, now you know. Besides not being particularly user friendly, it's &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/SearchResults.aspx?SearchQuery=WPF+2008"&gt;buggy as hell&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Today, while trying to demonstrate the basics of XAML / WPF, I was trying to show the design view of a WPF Window.  The problem was, every time I opened the designer, the IDE would just close.  No error, no beep, just gone.  That was awesome. &lt;br /&gt;&lt;br /&gt;Here are the things that I did that didn't solve the problem:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cursed.&lt;/li&gt;&lt;li&gt;Rebuilt all.&lt;/li&gt;&lt;li&gt;Cleaned solution, then rebuilt all.&lt;/li&gt;&lt;li&gt;Manually cleaned the solution by deleting the bin and object folders under each project in the solution.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Closed the solution and deleted the .suo file (Solution Options File).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Closed the solution and deleted the project user files.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Rebooted.&lt;/li&gt;&lt;li&gt;Cursed when it still didn't work.&lt;/li&gt;&lt;li&gt;Contemplated &lt;a href="http://en.wikipedia.org/wiki/Seppuku"&gt;Harakiri&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Here's what &lt;span style="font-style: italic;"&gt;did&lt;/span&gt; work:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Deleted all of the temp files in the temp directory. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;WTF?  So in XP, here is the temp directory that was causing the issue (it's a different path in Vista):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;    C:\Documents and Settings\&lt;username&gt;\Local Settings\Temp&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There were like almost 5,000 files in that directory.  Apparently, the designer creates temp files.  My best theory is that tt will keep bogging down trying to find unique temp file names until one day it runs out of combinations.  Then there is no &lt;a href="http://www.callforhelpinc.org/"&gt;call for help&lt;/a&gt;, no &lt;a href="http://www.porkjerky.com/free/suicide.php"&gt;suicide note&lt;/a&gt;, it just quietly and inexplicably goes away.  It doesn't even &lt;a href="http://people.howstuffworks.com/death-by-hanging.htm"&gt;hang itself&lt;/a&gt; (no process remains in Task Manager).&lt;br /&gt;&lt;br /&gt;I had discovered this fix many moons ago, and had of course forgotten about it until months later when my temp directory filled up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-8164799609195910434?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/8164799609195910434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=8164799609195910434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8164799609195910434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8164799609195910434'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/03/wpf-designer-causes-visual-studio-to.html' title='WPF Designer causes Visual Studio to Close'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9-lF1fc5euc/ScGdWBazT7I/AAAAAAAAAFw/_s0ARewos2g/s72-c/VisualStudio.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-47377806394551650</id><published>2009-03-05T10:14:00.004-05:00</published><updated>2009-03-05T10:35:32.328-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Nomadic Programming</title><content type='html'>No, I don't mean &lt;a href="http://www.nofluffjuststuff.com/blog/matthew_bass/2008/06/nomadic_programming.html"&gt;driving all around town to program&lt;/a&gt;... Which isn't to say that wouldn't be fun.  This refers to the tendency for a team to work on almost every module of a product at the same time.&lt;br /&gt;&lt;br /&gt;So, how do you tell if this is happening?  Draw a picture of your project.  Break down your project into its major components.  Pick a color scheme.  This one is pretty straightforward:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Red - the module hasn't been touched&lt;/li&gt;&lt;li&gt;Yellow - the module is in progress&lt;/li&gt;&lt;li&gt;Green - the module is code complete.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;And you'll end up with something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/Sa_uNzjQiII/AAAAAAAAAFg/auPhhF-uq2U/s1600-h/ProjectStatus.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 245px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/Sa_uNzjQiII/AAAAAAAAAFg/auPhhF-uq2U/s320/ProjectStatus.png" alt="" id="BLOGGER_PHOTO_ID_5309724406636906626" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Holy crap - there are very few modules that are complete, and very few that are untouched.   That means that the team is wandering all over the featurescape almost randomly coding on different modules.  This approach has all sorts of dangers:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; This makes it very hard to ever get a project done because no individual item ever is completed. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;This approach leads to the "throw it over the wall to testing at the end of a long development" method.  Not a good thing.  For example, a fundamental flaw in design / implementation could have happened months ago and propagated to the rest of the product.  That could easily lead to orders of magnitude to fix all of those issues.&lt;/li&gt;&lt;/ul&gt;If all is going well, we would expect to see a very small part of the diagram showing up in yellow (in progress) with the rest of the modules being either red (untouched) or green (completed).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-47377806394551650?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/47377806394551650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=47377806394551650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/47377806394551650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/47377806394551650'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/03/nomadic-programming.html' title='Nomadic Programming'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/Sa_uNzjQiII/AAAAAAAAAFg/auPhhF-uq2U/s72-c/ProjectStatus.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-2696632684098492692</id><published>2009-02-10T16:32:00.002-05:00</published><updated>2009-02-10T16:42:18.732-05:00</updated><title type='text'>Special Characters in the Office 2007 Ribbon</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/SZHydcL8ciI/AAAAAAAAAEQ/O6gCZtUY-ec/s1600-h/Office.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 130px; height: 107px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/SZHydcL8ciI/AAAAAAAAAEQ/O6gCZtUY-ec/s320/Office.jpg" alt="" id="BLOGGER_PHOTO_ID_5301284823988204066" border="0" /&gt;&lt;/a&gt;Have you ever run into a teeny little problem that was incredibly annoying and almost impossible to debug?  Well, I did.  All I wanted to do was create a Ribbon Tab at runtime from a database for a Word 2007 Add-In. &lt;br /&gt;&lt;br /&gt;Creating the tab and adding the controls was easy.  Very easy actually.  However, using"special characters" such as "'/" and "(" or ")" in the labels caused the entire tab to not be displayed.  No error message, no log, just poof - ribbon gone.  Sweet.    I tried escaping the characters xml style, but that caused even more problems.  I created a ribbon using the Visual Studio 2008 Ribbon Designer.  The code I had written looked almost exactly like the code there.  Well crap.  I Googled the living snot out of the problem and couldn't find a damn thing.  I asked team members.  I stared at the ceiling.  I mediated about it.  I even programmed myself to dream about it.  Actually, I gave up at the ceiling staring stage, but you get the idea.&lt;br /&gt;&lt;br /&gt;Well, today I was looking through the designer code for the ribbon, and it had calls to ribbon.SuspendLayout(), ribbon.ResumeLayout(False) around the calls to add the ribbon controls.  I didn't think this would do anything, but hey - why not give it go?  Sure enough, that fixed my problems. &lt;br /&gt;&lt;br /&gt;So, in summary, do this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;ribbon.SuspendLayout()&lt;br /&gt;&lt;br /&gt;... 'Add a bunch of tabs, groups, controls, etc&lt;br /&gt;&lt;br /&gt;ribbon.ResumeLayout(False)&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;and everything will be fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-2696632684098492692?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/2696632684098492692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=2696632684098492692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2696632684098492692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/2696632684098492692'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/02/special-characters-in-office-2007.html' title='Special Characters in the Office 2007 Ribbon'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/SZHydcL8ciI/AAAAAAAAAEQ/O6gCZtUY-ec/s72-c/Office.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-6496045657267003342</id><published>2009-01-06T09:30:00.006-05:00</published><updated>2009-01-06T10:49:58.478-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>XML Literals with namespaces</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9-lF1fc5euc/SWN9nSMYj7I/AAAAAAAAADY/k8r7LVltOXw/s1600-h/XML_Icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 100px; height: 57px;" src="http://3.bp.blogspot.com/_9-lF1fc5euc/SWN9nSMYj7I/AAAAAAAAADY/k8r7LVltOXw/s200/XML_Icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5288208501315243954" border="0" /&gt;&lt;/a&gt;I love Xml literals in VB.   They're pretty slick.  However, I ran into a little gotcha today...  All I wanted to do was query some data from an xml that happened to be part of a Word 2007 template (a .dotm file).   It looked like I had the right query syntax, but I wasn't getting any result.&lt;br /&gt;&lt;br /&gt;Most of the examples I found on the web were searching through xml like this:&lt;br /&gt;&lt;pre&gt;Dim document = &amp;lt;customers&amp;gt;&lt;br /&gt;            &amp;lt;customer firstname="John"&amp;gt;&amp;lt;/customer&amp;gt;&lt;br /&gt;            &amp;lt;customer firstname="Juliet"&amp;gt;&amp;lt;/customer&amp;gt;&lt;br /&gt;         &amp;lt;/customers&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;Dim firstNames = From customer In document.&amp;lt;customers&amp;gt;.&amp;lt;customer&amp;gt; _&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;                 Select customer.@firstName&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;This works like a champ.   firstNames contains what you would expect:&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;{Length=2}&lt;br /&gt;(0): "John"&lt;br /&gt;(1): "Juliet"&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;But let's say our xml is part of a namespace (much more realistic)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Dim document = &amp;lt;customers xmlns="http://fowlcoder.blogspot.com/xmlLiteralExample"&amp;gt;&lt;br /&gt;            &amp;lt;customer firstname="John"&amp;gt;&amp;lt;/customer&amp;gt;&lt;br /&gt;            &amp;lt;customer firstname="Juliet"&amp;gt;&amp;lt;/customer&amp;gt;&lt;br /&gt;         &amp;lt;/customers&amp;gt;&lt;br /&gt;&lt;/pre&gt;If we use the same query code as above, we don't get any results.  We actually have to add some code to make the query aware of the namespace.  It's pretty straightforward.&lt;br /&gt;&lt;br /&gt;First, add an Imports statement at the beginning of the file:&lt;br /&gt;&lt;pre&gt;Imports &amp;lt;xmlns:fc="http://fowlcoder.blogspot.com/xmlLiteralExample"&amp;gt;&lt;br /&gt;&lt;/pre&gt;Now, you have to alter the query a little bit:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Dim firstNames = From customer In document.&amp;lt;fc:customers&amp;gt;.&amp;lt;fc:customer&amp;gt; _&lt;br /&gt;                   Select customer.@firstName&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Voila!  You get the results that you would expect (John and Juliet).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-6496045657267003342?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/6496045657267003342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=6496045657267003342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/6496045657267003342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/6496045657267003342'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2009/01/xml-literals-with-namespaces.html' title='XML Literals with namespaces'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9-lF1fc5euc/SWN9nSMYj7I/AAAAAAAAADY/k8r7LVltOXw/s72-c/XML_Icon.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-1887755760509253091</id><published>2008-12-23T16:00:00.001-05:00</published><updated>2008-12-24T09:23:29.148-05:00</updated><title type='text'>How to destroy your business 101 - network security</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9-lF1fc5euc/SVJF255yp_I/AAAAAAAAAC4/x_SlDZRO8Go/s1600-h/Explode.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 150px;" src="http://2.bp.blogspot.com/_9-lF1fc5euc/SVJF255yp_I/AAAAAAAAAC4/x_SlDZRO8Go/s200/Explode.jpg" alt="" id="BLOGGER_PHOTO_ID_5283362122417481714" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Throughout the course of my career, I've had opportunities to work with a range of companies both large and small.   Along the way, I've seen some amazingly bad practices.   The root cause of each of these scenarios is usually a mixture of inexperience and/or laziness.  I'm not a network expert, but I know a bad idea when I see one.   Here are some example of grievous holes in security that I've run into first hand.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Shared Accounts&lt;/span&gt;&lt;br /&gt;Don't do it.  I've seen this manifest itself in few different ways.  At one shop, every member of the IT staff knew the password to the domain admin account.  This is bad.  The IT manager didn't realize that you could add accounts to the Domain Administrators &lt;span style="font-style: italic;"&gt;Group&lt;/span&gt;.  *sigh*  The thing is, if a bunch of people have access to the same account, it's almost impossible to tell who screwed something up.  Also, if it's hard to tell who dunnit, it's more likely that somebody is going to do it.  In other words, if you have a disgruntled employee in house that has domain admin access and you have no way to audit access,  he or she probably knows it and is free to wreak whatever havoc he or she wants to without much fear of getting caught.&lt;br /&gt;&lt;br /&gt;More recently, I saw the same problem from a different angle.  Instead of a bunch of people having the password to the domain admin account, everybody had the username / password to a test account that is part of the domain admin group.   Oh snap.  With these credentials, it would be possible to wreak devastation on the network with no trail.  This isn't a good.  The first thing I did was report this huge hole in security, so I'm hoping that somebody does something.    It's not my responsiblity, but I'd rather not have to twiddle my thumbs as the IT team rebuilds the servers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Easy passwords for sensitive accounts&lt;/span&gt;&lt;br /&gt;This was a legendary scenario.   Most companies use VPN to provide remote access to the corporate network.  The passwords for these accounts are usually required to have strong passwords at the the very least.  The robust solution should require certificates, SecureID fobs, etc.  I stumbled onto this one night when I was bored at home and was curious if I could guess the password to one of the salepersons accounts.  I fell out of my chair when I got it on my second guess.  Oh yeah, it was "password".&lt;br /&gt;&lt;br /&gt;Note that this was a large company, with over 300 employees that did many millions of dollars worth of business.  Oh, and it was a medical supply company.  Holy crap.  That was a huge violation of HIPAA rules.  I called the IT manager to fix the problem immediately.  He was worried that he would get support calls from the sales staff in the middle of the night so he didn't want to deal with it until the morning.   I knew that I would be the one fixing the problem if the network got comprimised, so I broke protocol and disabled the VPN server for the entire company.  I don't like sidestepping procedure but in this case I felt I had no choice.  The first thing in the morning I let the executive meeting what was happening.  Fortunately, the exec team understood the gravity of the matter and we resolved the issue pretty quickly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wireless&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;Access Points&lt;/span&gt;&lt;br /&gt;In another case, I was walking around the building I worked in.  While walking by the office of the IT manager, I noticed that there was a wireless router plugged into the network.  Snap.  I asked him what it was for and he stated that we was playing with it, but it was no big deal because it didn't have a big range.&lt;br /&gt;&lt;br /&gt;This was at the same company (and yes, the same IT manager).  Did I mention the gobs of patient data that we were responsible for?   I advised him that he probably should not be plugging that into the network.  He eventually saw my point, but I was amazed at the complete lack of forethought.&lt;br /&gt;&lt;br /&gt;There are ways to safely incorporate wireless networking into an enterprise architecture, but the right solution usually involves several layers of security including encryption, access control and firewalls.  Just plugging a cheap consumer wireless router into your office wall with default settings (wide open access) is a recipe for disaster.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mystery Machines&lt;/span&gt;&lt;br /&gt;At one post, I noticed there were several servers that were hanging out in the corner of the server room.  They weren't labeled and nobody had any idea what they did.  Better yet, nobody had the root password to the machines.  Holy crap!&lt;br /&gt;&lt;br /&gt;Basically, an intern had set up some servers for the company a while back, but never shared the passwords.  Out of fear, the IT manager refused to turn off the machine.  Later, when I became responsible for the network, the first thing I did was unplug those machines.  It turned out they were service some utility, but weren't critical.  I instructed the IT staff to recycle the machines with a fresh OS install so that we knew exactly what was installed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Finally&lt;/span&gt;&lt;br /&gt;There are many subtle ways in which network security can be comprimsed.  These were some gaping holes that were just asking for trouble.  Take an inventory, if you're doing any of the above - stop!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-1887755760509253091?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/1887755760509253091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=1887755760509253091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/1887755760509253091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/1887755760509253091'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/how-to-destroy-your-business-101.html' title='How to destroy your business 101 - network security'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9-lF1fc5euc/SVJF255yp_I/AAAAAAAAAC4/x_SlDZRO8Go/s72-c/Explode.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-8066217674937595240</id><published>2008-12-19T17:00:00.001-05:00</published><updated>2008-12-19T17:00:00.206-05:00</updated><title type='text'>Automation</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9-lF1fc5euc/STg2axt0WWI/AAAAAAAAAA0/AQYygSulCzk/s1600-h/circular.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 135px; height: 135px;" src="http://2.bp.blogspot.com/_9-lF1fc5euc/STg2axt0WWI/AAAAAAAAAA0/AQYygSulCzk/s320/circular.jpg" alt="" id="BLOGGER_PHOTO_ID_5276026797114546530" border="0" /&gt;&lt;/a&gt;I get bored easily.  I wouldn't make a good factory line worker because I'm horrible at repetition.   Once I've figured something out or gotten proficient at something, I lose interest for the most part (this excludes multiplayer first person shooter games - I can play those forever).  If I had to choose between working on an assembly line or wrestling rabid alligators, I would probably say something like "How big are the gators?"&lt;br /&gt;&lt;br /&gt;This isn't necessarily a bad thing (or at least that's what I tell myself).  When it comes to building software, I like to design and code, improve process - that sort of thing.  Doing repetitive things like running database scripts or running reports on project status are &lt;a href="http://en.wikipedia.org/wiki/Kryptonite"&gt;Kryptonite&lt;/a&gt; to me.  I would rather spend a few days building a tool to do the work for me than do it by hand every day / week, etc.&lt;br /&gt;&lt;br /&gt;What are good candidates for automation?  Pretty much anything that is repetitive.   &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Daily, Weekly, Monthly, Reports.&lt;/span&gt; &lt;br /&gt;Do whatever it takes to make these pushbutton.   This doesn't apply to one off reports.  However, if you're spending a bunch of time copying and pasting between Excel spreadsheets, you're doing something wrong.   If you automate the reporting process, any time spent daily is tweaking.  Tweaking is important for reporting.  If you're expending all of your energy just perfoming the mechanics of assembling the report, you're not as likley to make improvements to the report itself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Builds.&lt;/span&gt; &lt;br /&gt;Find a way to automate the build.  This is a continuous integration sort of thing, but it's a productivity enhancer.  Broken builds make broken teams.  Can you live without it?  Sure, on a small team it isn't too bad and I've worked that way plenty.  However, on a larger team, I can't imagine living without it.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Installers&lt;/span&gt;&lt;br /&gt;If you're using the Setup project type in Visual Studio, it's pretty easy, just build the setup project from the IDE.  If you're using install shield, find a way to script it / run it with nmake, etc so that you don't need the "install guy" (who is probably a coder responsible for a bunch of other things) to take time to "turn the build"  and make an installer.&lt;br /&gt;&lt;br /&gt;I ran into an extreme version of this at one shop where the build took something like 14 man hours to turn.  This one guy would go back to the build machine (it was the only environment where the build would work) in the closet and do his thing.  He eventually figured out how to script the whole thing with make files, but the manual process was ridiculous. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Odd bit&lt;/span&gt;&lt;br /&gt;There are plenty of opportunities.   While working at one place, the shiny new web server got set up just before the IT guy left for vacation.  Genius.  Of course, the site developed all sorts of problems and was going down every few minutes.&lt;br /&gt;&lt;br /&gt;We fixed the (numerous) issues and put it back into production.  This one guy was sitting there hitting the web site every few seconds to make sure that it was staying up.  I threw together a quick app that monitored the site and would make noise if the site went down.  He appreciated the help but was like "You must have too much time on your hands."  My response was "that's how I make time."  I try to invest a little bit of time up front so I don't waste time later.  It's a net gain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-8066217674937595240?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/8066217674937595240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=8066217674937595240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8066217674937595240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8066217674937595240'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/automation.html' title='Automation'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9-lF1fc5euc/STg2axt0WWI/AAAAAAAAAA0/AQYygSulCzk/s72-c/circular.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-3062829927882466189</id><published>2008-12-11T23:27:00.001-05:00</published><updated>2008-12-16T12:28:46.657-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Starting a new Dev project</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/SUHfUcHcG3I/AAAAAAAAABQ/Ypmdwyethd4/s1600-h/StartingNew.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 92px; height: 120px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/SUHfUcHcG3I/AAAAAAAAABQ/Ypmdwyethd4/s320/StartingNew.jpg" alt="" id="BLOGGER_PHOTO_ID_5278745780492704626" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;It's a glorious day.  You have the green light to start a new development project.     You can almost feel your hands on the keyboard typing out glorious code and coming up with fresh frameworks that are devoid of all that legacy that has been keeping you down.  Not so fast!  There are a lot of critical things that have to be in place for a project to be successful.  Here are some lessons I've learned from participating in the development of a number of projects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Process&lt;/span&gt;&lt;br /&gt;Pick a process.  It's 2008 for crying out loud.  Developing software without a process is just plain silly.  I've been a big fan of the iterative approach including &lt;a href="http://www.controlchaos.com/"&gt;Scrum&lt;/a&gt;.  Can you succeed with &lt;a href="http://en.wikipedia.org/wiki/Waterfall_model"&gt;waterfall&lt;/a&gt;?  Sure.  Even a blind squirrel finds a nut every now and then.  There's  a reason why most people cringe when they hear the word "waterfall." Even the creator of the process sites it as a generally bad idea.&lt;br /&gt;&lt;br /&gt;There are some different approaches, including &lt;a href="http://en.wikipedia.org/wiki/Spiral_development"&gt;Spiral Development&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Software_prototyping#Evolutionary_prototyping"&gt;Evolutionary Prototyping&lt;/a&gt;.   You can also go crazy and implement &lt;a href="http://en.wikipedia.org/wiki/CMMI"&gt;CMMI&lt;/a&gt;.  I  haven't used that particular model, but from what I hear it's pretty involved.  If you haven't developed using a software process before, I probably wouldn't start there.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Requirements&lt;/span&gt;&lt;br /&gt;Yup, you need them. There's no free lunch here.  What is there to justify?  This lesson has been learned over and over and over again.  Without a clear list of items to complete, nothing good will come.  Go down to a pretty low level of detail.  Items such as "Options Dialog" are very high level.  You should go down to the level of "The user shall be able to select a default font for the document. " The more work and detail you do at this point in the game makes the rest of the project go much, much faster.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Prototypes&lt;/span&gt;&lt;br /&gt;Prototypes are critical in proving technologies and approaches.  Within the source of a project I end up creating a number of prototypes.  Some of these are little one off sandboxes that I toss.   However, with most of these prototypes, there is some value in saving these as examples for other developers on the project, or as an easy way to capture the knowledge gained while sandboxing for later.  I usually create a folder in source control just for prototypes.&lt;br /&gt;&lt;br /&gt;Of course, if you're using the Evolutionary Prototype process, prototypes are bakes in.  If not, prototype each new piece of technology before adding it to the main source tree.  It's worth the time and will make sure that what you add to the main source tree is of decent quality.&lt;br /&gt;&lt;br /&gt;Also, if you're team is learning a new language for this new project, plan on throwing away the first attempt at building the product.  The only way to learn how to code is by doing it, but assume that the first iteration of building whatever widget you're working on will be crap.  You'll learn lots, but you'll need to rebuild it.  The good news is that when you do rebuild it, it will take a fraction of the time and the quality will be several orders of magnitudes better.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Source Control&lt;/span&gt;&lt;br /&gt;There are many options available for Source Control.  Just don't use Source Safe.  If you're thinking about using Source Safe, just shoot yourself in the foot.  Literally.  It will be as painful as trying to use Source Safe and will save time (including the hospital visit).  It's slow, unreliable, and horrible.  The lack of critical features such as atomic commits, not losing data, etc is unacceptable.    I've only used Source Safe and Team Foundation Server (TFS), so I don't have any advice to share for specific systems outside of those.  As far as TFS goes, there are pros and cons which I go into &lt;a href="http://fowlcoder.blogspot.com/2008/12/team-foundation-server-pros-and-cons.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Continuous Integration&lt;/span&gt;&lt;br /&gt;Do this from the beginning.  Make it easy for everyone to build the software.   This is a great opportunity for automation.   Different platforms have their own tools, but I'm a big fan of Team Build for TFS 2008.  It's pretty easy to set up and does most of what I want (although &lt;a href="http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fblogs.msdn.com%2Fbharry%2Farchive%2F2008%2F10%2F14%2Fpre-checkin-validation-for-tfs.aspx&amp;amp;ei=heJBSdLhOpagea7XnNwI&amp;amp;usg=AFQjCNGU49TIO9CAfVOs-R5Jxj9-oTu83w&amp;amp;sig2=zmGmIH1C4EGoiaT2wywgFQ"&gt;gating&lt;/a&gt; isn't going to come until TFS 2010 - aka &lt;a href="http://blogs.msdn.com/bharry/archive/2008/09/23/charting-a-course-for-tfs-rosario.aspx"&gt;Rosario&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installer&lt;/span&gt;&lt;br /&gt;If you application requires an installer, build one from the beginning.  As soon as you're past the prototype stage, build the installer and maintain it throughout the dev process.  Doing months of work then throwing it over the fence to the installer guy is a recipe for disaster.   The amazing thing is that I've seen this done more often than not.&lt;br /&gt;&lt;br /&gt;If you build this upfront, you'll be able to get feedback from the stakeholder much sooner in the process.  The shorter this feedback loop is, the less likely you'll be to stray too far away from what he / she / they expect.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Short Feedback Cycle&lt;/span&gt;&lt;br /&gt;Well, we just covered this in the installer bit, but it's worth mentioning on its own.  Schedule work in short enough increments (2 to 4/5 weeks seems to be the sweet spot range) that you can get feedback.  That breaks your work down into manageable bits and provides specific opportunities for the stakeholders to view the product (whether it's internal or external).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Internationalization&lt;/span&gt;&lt;br /&gt;Build it in from the ground up.  Yes.  Do it now.  I go into it in more detail &lt;a href="http://fowlcoder.blogspot.com/2008/12/internationalization.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Draw Pictures.&lt;/span&gt;&lt;br /&gt;Draw lots and lots of pictures.  Keep them around.  Whiteboards are the best for brainstorming (although it doesn't work well remotely).  Use Visio - it's great.  I've used the flowchart diagramming to do all sorts of things from program flow to installation scenarios.&lt;br /&gt;&lt;br /&gt;Have a big overview picture.  It's good stuff.  Hang it on the wall.  Keep it up to date.  It will help a lot of conversations to have the big picture to point at to talk about where problems are.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testing&lt;/span&gt;&lt;br /&gt;Do it.  Do it from the beginning.  Have a tester develop a test plan from the requirements.  Testing in flight will save sooooo much time.  Throwing a product over the wall to testing after months of coding is such a horrible idea it's staggering to know that there are still teams doing this.   If you want to get your product to market as fast as possible, this facet of the development process has the greatest impact on delivery time (not to mention product quality which ultimately effects support costs).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Unit Tests&lt;/span&gt;&lt;br /&gt;Yes do them.  Write your unit tests before you implement your code.  Having repeatable tests that you can run at the push of a button is magical.  If you can hook up those unit tests to an automatic build process, that's even better.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Code Reviews&lt;/span&gt;&lt;br /&gt;Code reviews are a stellar bang-for-the-buck proposition.  It is by far the cheapest way to reduce errors and ensure that the teams coding standards are followed.  This is also a good way to make sure that individual members of the team aren't reinventing the wheel.  I don't know how many times I've looked at someone's code on the team and said something like "oh hey, we already have something that does that.  Use it instead."  &lt;br /&gt;&lt;br /&gt;Code Reviews should start from the very beginning of the project.   Most likely, the code reviews will be the longest in the beginning of the project while the team is deciding on best practices.  As the project continues, the reviews should be done just as often, but they probably won't take nearly as long (if the project is going well) because the team should be in a groove and not drawing outside of the lines as much.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;There are a bunch of other things that you can do, but this is a good punch list of things that should be set up from the beginning of the project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-3062829927882466189?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/3062829927882466189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=3062829927882466189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/3062829927882466189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/3062829927882466189'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/starting-new-dev-project.html' title='Starting a new Dev project'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/SUHfUcHcG3I/AAAAAAAAABQ/Ypmdwyethd4/s72-c/StartingNew.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-3816846983465285761</id><published>2008-12-03T14:47:00.006-05:00</published><updated>2008-12-04T15:15:28.638-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='team build'/><title type='text'>Team Foundation Server - Pros and Cons</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/STdBW91QjNI/AAAAAAAAAAs/bXs0CGySfh0/s1600-h/VSTS.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 124px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/STdBW91QjNI/AAAAAAAAAAs/bXs0CGySfh0/s320/VSTS.jpg" alt="" id="BLOGGER_PHOTO_ID_5275757351298698450" border="0" /&gt;&lt;/a&gt;So you're shopping for a Source Control server.  There are a lot of options out there.  I've only used two systems in earnest: Source Safe (SS) and Team Foundation Server (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;TFS&lt;/span&gt;).   For the most part, I don't &lt;span style="font-style: italic;"&gt;hate&lt;/span&gt; too many products / technologies.  I'd like to think that I'm a pretty open minded guy.  However, I truly hate Source Safe.  I despise it.  I wish that it would go away and never bother anybody ever again.  It is a horribly outdated piece of crap technology that should never see the light of day.  If you're thinking about adopting Source Safe for a new project, don't.  Just stop.  Shoot yourself in the foot.  It will safe you time and will be less painful in the end.   &lt;a href="http://www.highprogrammer.com/alan/index.html"&gt;Alan De &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Smit&lt;/span&gt;&lt;/a&gt; does a good job detailing why Source Safe sucks in great detail &lt;a href="http://www.highprogrammer.com/alan/windev/sourcesafe.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are a number of other choices out there.  I've been particularly interested in trying &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;SourceGear&lt;/span&gt; Vault.  I've only gotten as far as downloading the trial - I never got around to installing it.  I've used their Source Off Site (SOS) product (it's a client / server piece which provides much faster WAN / &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;VPN&lt;/span&gt; access to a Source Safe database - it was absolutely brilliant).&lt;br /&gt;&lt;br /&gt;But, back to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;TFS&lt;/span&gt;.  Here's some background information that should help you get a feel for what you're getting into...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pros:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It's fast as hell, at least compared to Source Safe.   It's designed to run over a WAN and it communicates with the server via web services.  Getting latest is very efficient because &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;TFS&lt;/span&gt; only gives you what you need and doesn't need to check every file in your solution.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Integrates ever so nicely with Visual Studio.  It fits like a Glove into Visual Studio 2005 / 2008.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Atomic Commits.  In other words, if one file doesn't make it into a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;checkin&lt;/span&gt;, none of them make it.   That's the way it should be.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Comes with &lt;a href="http://fowlcoder.blogspot.com/2008/12/tfs-team-build.html"&gt;Team Build&lt;/a&gt;, which provides functionality that I hear is relatively similar to &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;CruiseControl&lt;/span&gt;.net&lt;/a&gt; (or so I've heard).&lt;br /&gt;&lt;/li&gt;&lt;li&gt; The work item subsystem is pretty sweet.  It has lots of features out of the box and is very extensible.  This is where you can store bugs, work items, etc.  It's not as full featured as &lt;a href="http://www.ibm.com/software/awdtools/clearcase/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;Clearcase&lt;/span&gt;&lt;/a&gt; or one of those systems, but it's adequate for doing most items.&lt;/li&gt;&lt;li&gt;Pretty solid extensibility.  You can add your own check in policies, access the work item / source control via &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;API&lt;/span&gt; (either via the client &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;API&lt;/span&gt; or through the service interface).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt; Cons&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Costs an arm and a leg.  You can get a 5 person &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;workgroup&lt;/span&gt; edition (for free with your &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;MSDN&lt;/span&gt; subscription), but you'll have to saw off your arm (and leg) to buy enough seats for 6 people.&lt;/li&gt;&lt;li&gt;Setup is a pain in the ass.  There are a &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_13"&gt;bazillion&lt;/span&gt; (well, not that many) prerequisites and it takes forever to get them all installed (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;SharePoint&lt;/span&gt;, this, that, etc).  Setting up the data tier on another machine takes some work as well.  It's definitely not a turnkey, just run Setup.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;exe&lt;/span&gt; and accept the defaults installation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Because installation is such a pain, recovery is a pain unless you backup the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;TFS&lt;/span&gt; as an image.  The good thing is that you only need two things in a worst case situation to restore a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;TFS&lt;/span&gt; server: The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;SQL&lt;/span&gt; Server database backup and the report private key.  Well, you can probably live without the key, but the instructions say that you need it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The work item system in its current implementation does not support &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_19"&gt;hierarchical&lt;/span&gt; data.  That (very important) feature is supposed to be supported in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;TFS&lt;/span&gt; 2010.  IMHO, you need a &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_21"&gt;hierarchy&lt;/span&gt; to do a &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_22"&gt;proper&lt;/span&gt; breakdown of any non-trivial project.  I actually moved all the breakdown information into MS Project (shudder) to get a better breakdown.&lt;/li&gt;&lt;li&gt;No keyword expansion.  This ruffled more than a few feathers as evidenced &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/1e29410e-26fb-4cce-a3d8-da68c69cd093/"&gt;here&lt;/a&gt;.   I've never used the feature in Source Safe, but to those who have used it, it is a sorely missed feature.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;No &lt;a href="http://social.msdn.microsoft.com/forums/en-US/tfsgeneral/thread/f9b1465e-ec6a-4641-88c5-754369bad05a/"&gt;sharing of files&lt;/a&gt;.   This one is a bit annoying.  While I've only used sharing sparingly, it's a very handy feature when you need it.&lt;/li&gt;&lt;li&gt;No &lt;a href="http://msdn.microsoft.com/en-us/library/byx8tbka%28VS.80%29.aspx"&gt;shadow folder&lt;/a&gt; support.  Once again, I've never used this feature.  However, if you've depended on it - you'll miss it.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;There are some notable differences for people that are used to Source Safe, such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;TFS&lt;/span&gt; keeps track of everything in a Workspace.  You have to get all the files that you want to work on before you can do anything.  Also, if you don't check out a file in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;TFS&lt;/span&gt;, but you just make it &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_25"&gt;writable&lt;/span&gt;, it will likely get overwritten because &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;TFS&lt;/span&gt; didn't know that you wanted to do that.   This causes all sorts of consternation for long time users of Source Safe.  &lt;a href="http://www.woodwardweb.com/"&gt;Martin Woodward&lt;/a&gt; does a good job of explaining &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;Workspaces&lt;/span&gt; &lt;a href="http://www.woodwardweb.com/teamprise/workspace_101_a.html"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Compares work a bit differently.  In Source Safe, if you do a compare of a directory, SS will literally compare every file byte for byte and report any differences (which could take an eternity).  On the other hand, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;TFS&lt;/span&gt; assumes that if you haven't checked out a particular file, it isn't different.   That's how &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;TFS&lt;/span&gt; operates so quickly.  Most of the time it works the way you want, but once again, it's different than how it worked in SS.&lt;/li&gt;&lt;/ul&gt;I'm sure that there are many more pros, cons and differences, but those are the big ones IMHO / experience.  Whatever Source Control solution you end up picking, make sure that you trial it to make sure that you can live with it.  Once you have a bunch of data in the source control database, it's usually non-trivial to move it to another server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-3816846983465285761?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/3816846983465285761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=3816846983465285761' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/3816846983465285761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/3816846983465285761'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/team-foundation-server-pros-and-cons.html' title='Team Foundation Server - Pros and Cons'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/STdBW91QjNI/AAAAAAAAAAs/bXs0CGySfh0/s72-c/VSTS.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-5517759585261384236</id><published>2008-12-03T10:20:00.007-05:00</published><updated>2008-12-03T21:47:13.302-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='team build'/><category scheme='http://www.blogger.com/atom/ns#' term='projectGuid'/><title type='text'>ProjectGuids in Project Reference</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9-lF1fc5euc/STakB2sG2OI/AAAAAAAAAAk/fGgN-cf_EZw/s1600-h/pulling-hair-out.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 156px; height: 190px;" src="http://2.bp.blogspot.com/_9-lF1fc5euc/STakB2sG2OI/AAAAAAAAAAk/fGgN-cf_EZw/s320/pulling-hair-out.jpg" alt="" id="BLOGGER_PHOTO_ID_5275584365278451938" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Why is it that it's always the little details that take the most time in any project / implementation?  In my &lt;a href="http://fowlcoder.blogspot.com/2008/12/tfs-team-build.html"&gt;recent efforts&lt;/a&gt; to get &lt;a href="http://msdn.microsoft.com/en-us/magazine/dd150090.aspx"&gt;Team Build&lt;/a&gt; up and running, I ran into some of the oddest things.  The one that had me pulling what's left of my hair out was a very small thing - the &lt;projectguid&gt;.&lt;br /&gt;&lt;br /&gt;Normally, in the course of developing a .NET project, you can pretty much ignore the little details like what the projectGuid is for a given project.  The problem that I ran into is that one of the project references had an oudated value.&lt;br /&gt;&lt;br /&gt;This is the little beasty that was causing all of the issues (this is in the raw xml of the .vbproj file):&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/projectguid&gt;&lt;blockquote&gt;&lt;projectguid&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;projectReference include="..\MyClassLibrary.vbproj"&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/projectguid&gt;&lt;span style="font-size:85%;"&gt;&lt;projectguid&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   &amp;lt;name&amp;gt;MyClassLibrary&amp;lt;/name&lt;/span&gt;&lt;/projectguid&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;projectguid&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   &amp;lt;project&gt;{D5D5C0F8-6BEB-4415-9CA0-E2A84B8D32B6}&lt;/span&gt;&lt;/projectguid&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;   &amp;lt;package&gt;{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&amp;lt;/package&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/projectReference&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;projectguid&gt;&lt;/projectguid&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;It's rare that a projectGuid will ever change.  In this case, we had to make the MyClassLibrary a VSTO plug in for word.   I didn't do the conversion (and wouldn't have caught something like the projectGuid changing if I did), but for some bizarre reason we ended up with a new projectGuid for MyClassLibrary.&lt;br /&gt;&lt;br /&gt;This is the little bugger that changed in the MyClassLibrary.vbproj file:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="font-family:courier new;"&gt;&lt;projectguid&gt;&lt;/projectguid&gt;&lt;/span&gt;{D5D5C0F8-6BEB-4415-9CA0-E2A84B8D32B6}&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;The fix was simple, all I had to do was copy the correct Guid to the &lt;projectreference&gt; tag of the other project and I was good to go.  Finding that was absolutely horrible though.&lt;br /&gt;&lt;br /&gt;Along the path, I found out that the solution would actually build after a complete rebuild.  Apparently there is some voodoo happening with the ResolveAssemblyReference.cache files.  I'm guessing that these "fix up" the references without changing anything in the original .vbproj files.  We didn't notice it in our local build environment because these files were already generated with the correct overriding information.  However, the build machine always grabs the source to a clean directory, so these files haven't been generated yet.&lt;/projectreference&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-5517759585261384236?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/5517759585261384236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=5517759585261384236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/5517759585261384236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/5517759585261384236'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/projectguids-in-project-reference.html' title='ProjectGuids in Project Reference'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9-lF1fc5euc/STakB2sG2OI/AAAAAAAAAAk/fGgN-cf_EZw/s72-c/pulling-hair-out.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-8918886485241650927</id><published>2008-12-02T13:58:00.005-05:00</published><updated>2008-12-02T14:35:15.780-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='team build'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>TFS Team Build</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/STWFlaWAdoI/AAAAAAAAAAc/meiju9EZu9s/s1600-h/TeamBuild.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 150px; height: 113px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/STWFlaWAdoI/AAAAAAAAAAc/meiju9EZu9s/s320/TeamBuild.gif" alt="" id="BLOGGER_PHOTO_ID_5275269416307684994" border="0" /&gt;&lt;/a&gt;It was the best of times, it was the worst of times.  &lt;a href="http://msdn.microsoft.com/en-us/library/ms181710%28VS.80%29.aspx"&gt;Team Build&lt;/a&gt; (as included in &lt;a href="http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Ftfs2008%2Fdefault.aspx&amp;amp;ei=84U1ScDYFYuueY_l7fcH&amp;amp;usg=AFQjCNFyoEgp8e58wkAwt4ka0xrIwOx4Ag&amp;amp;sig2=duzbzi84WvBuZ9GiL0QNSA"&gt;Team Foundation Server 2008&lt;/a&gt;) is a very powerful tool which can save all sorts of time by automatically building your code every time somebody checks something in.  I've never used it, but TFS is supposed to do a lot of the things that &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;Cruise Control.NET&lt;/a&gt; does out of the box.  That said, it can be a pain tracking down all the resources you'll need to get your solution compiling like a champ.  Here's what I did / used.&lt;br /&gt;&lt;br /&gt;For the most part, getting started is pretty straightforward.  However, there are a few gotchas.  In general, you want a dedicated server to do the team builds.  To get started with that, you need to &lt;a href="http://msdn.microsoft.com/en-us/library/ms181712.aspx"&gt;install&lt;/a&gt; the build agent on that machine.  The installation bits are on the Team Foundation Server install disc.  The important part here is to set up the build service to run under an account that has access to TFS.  If you screw this up the first time, just go into services and change the username / credentials for the "Visual Studio Team Foundation Build" (don't forget to restart the service).&lt;br /&gt;&lt;br /&gt;After you've installed that, you need to set up your workspace.  I followed &lt;a href="http://blogs.msdn.com/buckh/archive/2007/08/14/tfs-2008-a-basic-guide-to-team-build-2008.aspx"&gt;Buck Hodge's&lt;/a&gt; advice on getting that going.&lt;br /&gt;&lt;br /&gt;Now, some special cases.  If you are signing any of your assemblies with a .pfx key, you'll want to import that onto the local machine.  Here's some &lt;a href="http://www.finalbuilder.com/Default.aspx?tabid=53&amp;amp;aff=1&amp;amp;aft=7070&amp;amp;afv=topic"&gt;advice&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Another item to keep in mind is that the solution will be built with a slightly different folder structure.  This can cause problems if you have a post build step that copies files (e.g. if you have some plug in type files that aren't directly referenced by the main application project but the app needs them to run).&lt;br /&gt;&lt;br /&gt;This approach work fine on the local machine, but not on the build server.  To make something like this:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;copy "$(TargetPath)" "$(SolutionDir)MyApp\bin\Debug"&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;work on the build machine, you can do something like this:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;IF EXIST "$(SolutionDir)MyApp\bin\Debug" copy "$(TargetPath)" "$(SolutionDir)MyApp\bin\Debug"&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;That should work in most cases (your mileage may vary).&lt;br /&gt;&lt;br /&gt;I haven't tried setting up an unit tests to run automatically.  If / when I'll do, I'll likely post about that too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-8918886485241650927?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/8918886485241650927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=8918886485241650927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8918886485241650927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/8918886485241650927'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/tfs-team-build.html' title='TFS Team Build'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/STWFlaWAdoI/AAAAAAAAAAc/meiju9EZu9s/s72-c/TeamBuild.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-1216161722801077971</id><published>2008-12-01T12:53:00.000-05:00</published><updated>2008-12-01T13:14:47.923-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='starting a project'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='internationalization'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Internationalization</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9-lF1fc5euc/STQpi3puc6I/AAAAAAAAAAM/YVzNznjVcx8/s1600-h/elbonians.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 112px; height: 134px;" src="http://4.bp.blogspot.com/_9-lF1fc5euc/STQpi3puc6I/AAAAAAAAAAM/YVzNznjVcx8/s320/elbonians.gif" alt="" id="BLOGGER_PHOTO_ID_5274886742588945314" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;How many times have you gone through this scenario?  You start out a project, and you ask all the right questions including:&lt;br /&gt;&lt;blockquote&gt;Will this application ever need to support multiple languages?&lt;br /&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;More often than not, this answer will be "No, that's crazy.  Don't add support for that.  It will take way too much time".&lt;br /&gt;&lt;br /&gt;Now fast forward months / years into that project.  How many times do you find out (usually in a conference call) that some huge customer in &lt;a href="http://en.wikipedia.org/wiki/Elbonia"&gt;Elbonia&lt;/a&gt; that wants to buy a bazillion licenses of your software, but only if it's localized in &lt;a href="http://en.wikipedia.org/wiki/Swahili"&gt;Swahili&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is the part of the story where the developers usually try to explain how difficult such an endeavor would be and that the next planned release will be postponed by orders of magnitude.&lt;br /&gt;&lt;br /&gt;As in most cases, an ounce of prevention is worth more than a pound of cure.  The only way to avoid this miserable situation is to build in internationalization support from the beginning.   There are numerous objections to supporting this from the beginning:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It will take too much time to add support for multiple languages&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It's too burdensome to add new strings&lt;/li&gt;&lt;li&gt;Working with the UI is too much of a pain&lt;/li&gt;&lt;/ul&gt;These concerns can't be dismissed.  These are valid complaints / obstacles.  However, it's worth pointing out that there are some benefits to going this route from the beginning, even if the &lt;a href="http://en.wikipedia.org/wiki/Pointy-Haired_Boss"&gt;PHB &lt;/a&gt;never makes the dreaded "We need to sell this thing in Russian" call:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;All of the strings are in one place, so it's easy to maintain phrasing style for the whole project even with multiple developers.&lt;/li&gt;&lt;li&gt;Common strings can be reused (e.g. Cancel, OK, Username, etc).  If a decision is made to change one of those, it gets changed everywhere.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Testers can usually make changes to spelling, phrasing, etc without bothering the developers.  I've spent way too much time correcting spelling, phrasing errors when a tester could have just done it themselves if they had ready access to the strings.&lt;/li&gt;&lt;/ul&gt;Oh, and when you get the last minute call that you need to translate the product, it will be no big deal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-1216161722801077971?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/1216161722801077971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=1216161722801077971' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/1216161722801077971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/1216161722801077971'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/12/internationalization.html' title='Internationalization'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9-lF1fc5euc/STQpi3puc6I/AAAAAAAAAAM/YVzNznjVcx8/s72-c/elbonians.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6152905331119398238.post-341929126387833112</id><published>2008-11-07T09:07:00.001-05:00</published><updated>2008-12-01T18:32:52.299-05:00</updated><title type='text'>Damn, I'm not spamming!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9-lF1fc5euc/STR0G_qPAyI/AAAAAAAAAAU/2rtCTndhuUs/s1600-h/spam.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 124px; height: 105px;" src="http://1.bp.blogspot.com/_9-lF1fc5euc/STR0G_qPAyI/AAAAAAAAAAU/2rtCTndhuUs/s320/spam.jpg" alt="" id="BLOGGER_PHOTO_ID_5274968727074308898" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Wow, this blog is off to an amazing start...  I haven't even had a chance to post anything, and google has marked this blog as a potential spam blog.&lt;br /&gt;&lt;br /&gt;Here is the message I received:&lt;br /&gt;&lt;blockquote&gt;Your blog at: &lt;a href="http://fowlcoder.blogspot.com/" target="_blank"&gt;http://fowlcoder.blogspot.com/&lt;/a&gt; has been identified as a potential spam blog.  To correct this, please request a review by filling out the form at &lt;a href="http://www.blogger.com/unlock-blog.g?lockedBlogID=6152905331119398238" target="_blank"&gt;&lt;/a&gt;[link removed].&lt;br /&gt;&lt;br /&gt; Your blog will be deleted in 20 days if it isn't reviewed, and your readers will see a warning page during this time. After we receive your request, we'll review your blog and unlock it within two business days. Once we have reviewed and determined your blog is not spam, the blog will be unlocked and the message in your Blogger dashboard will no longer be displayed. If this blog doesn't belong to you, you don't have to do anything, and any other blogs you may have won't be affected.&lt;br /&gt;&lt;br /&gt; We find spam by using an automated classifier. Automatic spam detection is inherently fuzzy, and occasionally a blog like yours is flagged incorrectly. We sincerely apologize for this error. By using this kind of system, however, we can dedicate more storage, bandwidth, and engineering resources to bloggers like you instead of to spammers. For more information, please see Blogger Help: &lt;a href="http://help.blogger.com/bin/answer.py?answer=42577" target="_blank"&gt;http://help.blogger.com/bin/&lt;wbr&gt;answer.py?answer=42577&lt;/a&gt;&lt;/blockquote&gt;So, hint to all new bloggers using blogger.com - fill out some profile information and post something, or you'll have to go through this process as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6152905331119398238-341929126387833112?l=fowlcoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fowlcoder.blogspot.com/feeds/341929126387833112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6152905331119398238&amp;postID=341929126387833112' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/341929126387833112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6152905331119398238/posts/default/341929126387833112'/><link rel='alternate' type='text/html' href='http://fowlcoder.blogspot.com/2008/11/damn-im-not-spamming.html' title='Damn, I&apos;m not spamming!'/><author><name>Rich Quackenbush</name><uri>http://www.blogger.com/profile/17253533756508946641</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9-lF1fc5euc/STR0G_qPAyI/AAAAAAAAAAU/2rtCTndhuUs/s72-c/spam.jpg' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
