<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>thirstycrow</title>
  <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/" />
  <link rel="self" href="http://thirstycrow.net/blog/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2008-07-21T07:46:55.838-07:00</updated>
  <author>
    <name>thirstycrow.net</name>
  </author>
  <subtitle>.net programming for the web and the desktop.</subtitle>
  <id>http://thirstycrow.net/blog/</id>
  <generator uri="http://dasblog.info/" version="2.1.8102.813">DasBlog</generator>
  <entry>
    <title>Spamollow: Using Twitter 'Follow' As A Spam Vector</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/07/21/SpamollowUsingTwitterFollowAsASpamVector.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,d1ffc06a-9966-4e56-882b-5271e0ea42dd.aspx</id>
    <published>2008-07-21T07:46:55.838-07:00</published>
    <updated>2008-07-21T07:46:55.838-07:00</updated>
    <category term="Twitter" label="Twitter" scheme="http://thirstycrow.net/blog/CategoryView,category,Twitter.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I'm not sure if there is a term for following someone on Twitter just to get them
to click on your link but I'm suggesting the following:
</p>
        <p>
          <strong>Spamollow:</strong> (verb)
</p>
        <ol>
          <li>
To follow someone on Twitter for the purpose of getting the user being followed to
click on a link they would not otherwise in their worst moments of depravity or boredom
click on.</li>
        </ol>
        <p>
          <strong>Spamollower:</strong> (noun)
</p>
        <ol>
          <li>
One who spamollows.</li>
          <li>
A parasite.</li>
        </ol>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=d1ffc06a-9966-4e56-882b-5271e0ea42dd" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Vacation</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/07/08/Vacation.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,4daca4f0-a9a3-4f96-97a9-ac78f9ccd42e.aspx</id>
    <published>2008-07-08T07:21:09.104375-07:00</published>
    <updated>2008-07-08T07:21:09.104375-07:00</updated>
    <category term="Off Topic" label="Off Topic" scheme="http://thirstycrow.net/blog/CategoryView,category,OffTopic.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="154" alt="Sea Oats" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/seaoats.jpg" width="620" border="0" />
        </p>
        <p>
I've had jobs where on Friday afternoon I was already dreading Monday morning. 
Not now; I love what I do.  I get paid to do what I would (and do) do for free.  
Still, it's always a challenge to spool back up after vacation.  
</p>
        <p>
Here are a few photos from the <a href="http://www.ncaquariums.com/" target="_blank">North
Carolina Aquarium at Fort Fisher</a>.
</p>
        <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="199" alt="Weeds" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/weeds.jpg" width="620" border="0" />
        <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="220" alt="Coperhead" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/coperhead.jpg" width="367" border="0" />
        <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="214" alt="Lookdowns" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/lookdowns.jpg" width="260" border="0" />
        <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="242" alt="Tree Frog" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/frog.jpg" width="270" border="0" />
        <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="245" alt="Jellyfish" src="http://thirstycrow.net/blog/content/postimages/Vacation_8F14/jellyfish.jpg" width="320" border="0" />
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=4daca4f0-a9a3-4f96-97a9-ac78f9ccd42e" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Adventures of a Lead Programmer in a One-man Shop: Episode 5 - TeamCity Configuration</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/25/AdventuresOfALeadProgrammerInAOnemanShopEpisode5TeamCityConfiguration.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,75aa1e03-c326-4a17-946e-d8cd3a14c78f.aspx</id>
    <published>2008-06-25T06:06:31.0113216-07:00</published>
    <updated>2008-06-25T06:06:31.0113216-07:00</updated>
    <category term="Continuous Integration" label="Continuous Integration" scheme="http://thirstycrow.net/blog/CategoryView,category,ContinuousIntegration.aspx" />
    <category term="MSBuild" label="MSBuild" scheme="http://thirstycrow.net/blog/CategoryView,category,MSBuild.aspx" />
    <category term="TeamCity" label="TeamCity" scheme="http://thirstycrow.net/blog/CategoryView,category,TeamCity.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
In the previous episode I intended to cover the configuration of TeamCity, but took
a quick detour to talk about MSBuild and MSBuild scripts.  Now that we've got
a script to use we can configure TeamCity.  The following will be the minimal
steps to get up an running.
</p>
        <ol>
          <li>
To start off, log into your TeamCity installation and click on the <strong>Administration</strong> button
(top right area of screen) to go to the <strong>Projects and Build Configurations</strong> screen. 
This screen will give you an overview of all the projects that you have configured
to run on this installation.  
</li>
          <li>
Click on the <strong>Create Project</strong> link on the page.  Name your project
and give it a description then click the <strong>Create</strong> button. 
</li>
          <li>
The next screen will provide you will the options for creating a build configuration
and a VCS root.  Here are the values I used under the heading of <strong>General
Settings</strong>:<br /><ul><li><strong>Name:</strong> Something that makes sense in your context (i.e., Standard
MSBuild). 
</li><li><strong>Build number format:</strong> I'm currently using 2.0.{0}.{build.vcs.number.1} 
The initial 2.0 is static, but {0} is a placeholder for the build counter value. 
The {build.vcs.number.1} placeholder is, as the note below the text box says "a reference
to VCS changeset number.  So for example 2.0.71.144 means the 71st build using
revision 144 of 2.0.  There are different strategies for version number make
up.  The important thing is to pick something that works for you and stick with
it. 
</li><li><strong>Build counter:</strong> This allows you to set the build number to a higher
seed if for instance you're migrating from another configuration where you've already
reached build number.  Conversely, you can also decrement the value if you want
to zero the build counter. 
</li><li>
Click on <strong>VCS settings</strong> button to continue with the setup.</li></ul></li>
          <li>
            <strong>Version Control Settings</strong> are next.  
<ul><li>
Click on <strong>Create and attach a new VCS root</strong>. 
</li><li>
Enter a meaningful name and choose the appropriate type of VCS, in my case Subversion. 
</li><li>
Fill in the blanks for the URL, and if necessary, user name and password.  There
is an option to test the connection at the bottom of the page.  
</li><li>
Save your changes to return to the previous page. 
</li><li>
Back on the <strong>Version Control Settings</strong> I chose <strong>Automatically
on server</strong> for the <strong>VCS checkout mode</strong> and left the rest of
the settings unchanged.  Click the <strong>Choose Build Runner</strong> button
to advance. 
</li></ul></li>
          <li>
From the <strong>Build runner</strong> options I chose MSBuild.  The next parameter, <strong>Build
file path</strong>, took me a couple of tries to get right the first I set this up. 
The note under the text box says "Specified path should be relative to the checkout
directory" but keep in mind that your URL choice in the <strong>VCS root</strong> options
will influence the relative path.  If you have a traditional directory structure
of branches, tags, and trunk at your VCS root and specify the root of your source
tree then your <strong>Build file path</strong> may look something like trunk\MyBuildScript.xml. 
Two MSBuild versions should be available, the one from the 2.0 and the 3.5 version
of the .NET Framework.  I would suggest 3.5 even if you're building a Visual
Studio 2005 project.  Click <strong>Save</strong>.</li>
        </ol>
        <p>
At this point all of the necessary steps have been completed.  However, TeamCity
offers more options that can be configured around your project.  The options
are listed on the right side of the screen under<strong> Build Configuration Steps</strong> heading
when you're editing a project.  All of these options are also available from
the <strong>Edit Configuration Settings</strong> link on the project tool bar. 
One of the options in particular is worth considering - <strong>Build Triggering</strong>. 
TeamCity offers many options for triggering a build.  The one I found most useful
is VCS Triggers.  TeamCity can check for any changes to your source control repository
on the interval you choose and run a new build with the changes.  
</p>
        <p>
In order to make use of your project you need to have an authorized build agent available. 
Click on the <strong>Agents</strong> tab in the top left area of the screen. 
Under the Agents heading you will see four tabs.  One of them (probably the <strong>Unauthorized
agents</strong> tab) should have a number greater than zero in parenthesis. 
Click on that tab.  If it is the <strong>Unauthorized agents</strong> tab click
on the <strong>Authorize agent</strong> link then move over to the <strong>Connected
Agents</strong> tab and click the <strong>Enable agent</strong> link if necessary. 
Your agent is now available for use.
</p>
        <p>
With your project completed you will find it listed under the <strong>Projects</strong> tab
(top left area of screen).  Choose your project from the drop down menu embedded
in the <strong>Project</strong> tab.  Under the <strong>Current status</strong> section
of the <strong>Overview</strong> tab if you have a <strong>No suitable agents</strong> link
return to the previous paragraph and check your settings.  From this screen you
can trigger a build by clicking on the <strong>Run</strong> button in the toolbar. 
After a second or two the page will refresh and show you the status of the build as
it progresses.  The build result will be shown in the <strong>Recent history</strong> section
of the page.  
</p>
        <p>
A word about troubleshooting a failed build: If the build fails you can use the drop
down menu in the history list beside the result in the <strong>Results</strong> column
to view the build messages to guide your troubleshooting.  A couple of things
that have tripped me up are forgetting to add a newly referenced dll to source control. 
Along the same lines, referencing a new dll and not updating the MSBuild script accordingly
caused a failed build.  If you have no idea where to begin troubleshooting start
by running the script locally from a Visual Studio command prompt.  See the end
of <a href="http://thirstycrow.net/blog/2008/05/27/AdventuresOfALeadProgrammerInAOnemanShopEpisode4MSBuildScript.aspx" target="_blank">Episode
4</a> for more information.
</p>
        <p>
If you're new to TeamCity I would suggest spending the time to explore the interface
and become familiar with the many available options.  As I said at the start
of this post, I've only covered the minimal step to get you up and running from a
cold start.  
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=75aa1e03-c326-4a17-946e-d8cd3a14c78f" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Error: Subreport could not be shown</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/23/ErrorSubreportCouldNotBeShown.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,63f9adb0-2e92-4bbc-8aaa-a6d1ecd43f17.aspx</id>
    <published>2008-06-23T07:24:27.970625-07:00</published>
    <updated>2008-06-23T07:24:27.970625-07:00</updated>
    <category term="Reporting Services" label="Reporting Services" scheme="http://thirstycrow.net/blog/CategoryView,category,ReportingServices.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
We tell our kids that "hate" is a strong word and to be careful about the words they
choose because they reflect the content of their hearts.  That said - I hate
making subreports in Visual Studio.  I do it just infrequently enough to forget
all the little things you have to do to get them working.  Consequently I end
up looking at the world's most useless error message: "Error: Subreport could not
be shown".  Never again my friend; this time I'm going to write it down.
</p>
        <p>
In my experience a lot has to go right and pretty much nothing wrong when setting
up a subreport for it to work.  I adhere to the following <strike>voodoo rituals</strike> guidelines: 
</p>
        <ul>
          <li>
If you can avoid subreports altogether, then do. 
</li>
          <li>
Remember to configure the parameters for the subreport itself.  The configuration
dialog is accessed by right-clicking on the design surface outside of the report boundaries
(the gray area) and choosing "Report Parameters" from the context menu. 
</li>
          <li>
The first time you drag a column from a data source table onto the parent report the
IDE makes a reference to that data source in its underlying XML.  Be sure to
do this for at least one column of each table that will serve as sources for parameters
in a given subreport before configuring the subreport.  Doing this will ensure
that the source columns will be available in the subreport configuration dialog of
the parent report.  
</li>
          <li>
When you specify the report to show in the parent report's subreport control, remember
to configure the parameters on the "Parameters" tab of the configuration dialog. 
The dialog is accessed by right-clicking the control.  All of the subreport parameters
(Parameter Name) must be specified along with their source (Parameter Value). 
Watch for spelling and case errors. 
</li>
          <li>
If you have to modify a table adapter in a typed dataset used by a subreport and that
modification adds a column to the table adapter, then it is better to delete the table
adapter from the typed dataset and recreate it with the same name with the necessary
changes.  I just recently tried modifying an existing table adapter in this way
and broke a report that had been working.  Yea, I know.  It's crazy. 
</li>
          <li>
Sadly, It is often easier and faster to delete and recreate a subreport (and if necessary
its parent report) than to troubleshoot one that isn't working.</li>
        </ul>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=63f9adb0-2e92-4bbc-8aaa-a6d1ecd43f17" />
      </div>
    </content>
  </entry>
  <entry>
    <title>17 Year Cicadas</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/17/17YearCicadas.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,6487f912-ee70-4f2c-92d9-64df22707627.aspx</id>
    <published>2008-06-17T13:16:27.828125-07:00</published>
    <updated>2008-06-17T13:19:14.46875-07:00</updated>
    <category term="Off Topic" label="Off Topic" scheme="http://thirstycrow.net/blog/CategoryView,category,OffTopic.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 10px 10px; border-right-width: 0px" height="189" alt="cicada2" src="http://thirstycrow.net/blog/content/postimages/17YearCicadas_E374/cicada2.jpg" width="220" align="right" border="0" />
          <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 10px 10px 0px; border-right-width: 0px" height="320" alt="cicada" src="http://thirstycrow.net/blog/content/postimages/17YearCicadas_E374/cicada.jpg" width="178" align="left" border="0" />The
17 year cicadas are out.  They were so loud this weekend that I could hear them
over the lawnmower while wearing earplugs.  I took these shots in the back yard. 
It was on the cherry tree.  We actually still have cherries this year because
the birds are eating these guys instead of the fruit.  
</p>
        <p>
I'm sure the cherries will be gone shortly after the cicadas. 
</p>
        <p>
 
</p>
        <p>
 
</p>
        <ul>
          <li>
Relevant Links:<br /><a title="http://insects.ummz.lsa.umich.edu/fauna/michigan_cicadas/Periodical/Index.html" href="http://insects.ummz.lsa.umich.edu/fauna/michigan_cicadas/Periodical/Index.html" target="_blank">Periodical
Cicada Page</a></li>
          <li>
            <a title="http://en.wikipedia.org/wiki/Cicada" href="http://en.wikipedia.org/wiki/Cicada" target="_blank">Wikipedia
Entry About Cicadas</a>
          </li>
        </ul>
        <br style="clear: both" />
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=6487f912-ee70-4f2c-92d9-64df22707627" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Tim Russert: In Memoriam</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/13/TimRussertInMemoriam.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,f19c1cb0-6582-41a5-aee8-831ff2b5bedc.aspx</id>
    <published>2008-06-13T14:48:11.65625-07:00</published>
    <updated>2008-06-13T14:51:06.78125-07:00</updated>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I am truly saddened to hear about the death of Tim Russert today at the age of 58. 
You'll see the Meet The Press feed in my blogroll.  I watched MTP every Monday
during lunch.  Russert in interviews and during the Sunday broadcast showed himself
to be a man of skill, intelligence, and most of all genuine integrity.  In a
media landscape of extremes with Fox News and CNN as bookends he kept his personal
opinions to himself and interviewed each guest thoroughly and impartiality. 
I trusted him.  We have all lost one of the last true journalist.  He cannot
be replaced, and his untimely death, particularly in this election season, is a great
loss.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=f19c1cb0-6582-41a5-aee8-831ff2b5bedc" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Fabulous Free Icons - Silky Smooth, And Everywhere You Look</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/12/FabulousFreeIconsSilkySmoothAndEverywhereYouLook.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,ebaf1b84-485b-4b8c-b401-a06eba2b73b9.aspx</id>
    <published>2008-06-12T09:11:33.2945-07:00</published>
    <updated>2008-06-12T09:12:55.153875-07:00</updated>
    <category term="Web Design" label="Web Design" scheme="http://thirstycrow.net/blog/CategoryView,category,WebDesign.aspx" />
    <category term="WinForms" label="WinForms" scheme="http://thirstycrow.net/blog/CategoryView,category,WinForms.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 10px 0px 0px; border-right-width: 0px" height="84" alt="FamFamFam Icons" src="http://thirstycrow.net/blog/content/postimages/FabulousFreeIconsSilkySmooth_98B9/famfamfam.png" width="84" align="left" border="0" />
          <em>This
another Frankenpost from the previous version of the blog, but I'm adding new content
to the end.</em>
        </p>
        <p>
Mark James over at <a href="http://famfamfam.com/">FamFamFam</a> has made available
to the public a <a href="http://www.famfamfam.com/lab/icons/silk/">free set of 1000
icons</a> (nope, that's not a typo) called Silk.  It's just one of three currently
available.  As you can see from this preview, the icons are high quality.
</p>
        <p>
          <strong>Here's the new part:</strong>
          <br />
The reason I found the FamFamFam collection was that I needed some icons for <a href="http://happyfish.info/" target="_blank">HappyFish</a>. 
I love the collection and have spent so much time looking at them that I can spot
one instantly.  That's why when I updated my installation of <a href="http://www.twhirl.org/" target="_blank">twhirl</a> I
recognized one of the FamFamFam icons on a little dialog advertising a new feature.  <a href="http://www.screwturn.eu/" target="_blank">ScrewTurn
Wiki</a> makes use of them too.  I'm going to be using ScrewTurn for the new
HappyFish wiki.  As for twhirl, I recommend it as a desktop Twitter client. 
It has integration with <a href="http://friendfeed.com/" target="_blank">FriendFeed</a> which
is a nice bonus.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=ebaf1b84-485b-4b8c-b401-a06eba2b73b9" />
      </div>
    </content>
  </entry>
  <entry>
    <title>CSS + JavaScript = Alternative to Framesets</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/06/12/CSSJavaScriptAlternativeToFramesets.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,7deb9537-7840-44c2-9ebd-0cb71ab27e2d.aspx</id>
    <published>2008-06-12T07:28:18.075-07:00</published>
    <updated>2008-06-12T07:29:25.607-07:00</updated>
    <category term="asp.net" label="asp.net" scheme="http://thirstycrow.net/blog/CategoryView,category,aspnet.aspx" />
    <category term="CSS" label="CSS" scheme="http://thirstycrow.net/blog/CategoryView,category,CSS.aspx" />
    <category term="Web Design" label="Web Design" scheme="http://thirstycrow.net/blog/CategoryView,category,WebDesign.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>This is a Frankenpost - it was on the blog before I migrated from Community Server
to DasBlog.  It's one that I find useful so I'm porting it over.</em>
        </p>
        <p>
Here's something I cobbled together as a replacement for a frameset. The technique
takes advantage of the overflow CSS property applied to the HTML doc and a div within
it to achieve the appearance of a frameset.  I used it in a MasterPage scenario,
but it would work on a single page just as well.  
</p>
        <p>
First you need to structure your page something like this:
</p>
        <div class="divCodeBlock">&lt;body &gt;<br />
    &lt;form id="form1" runat="server"&gt;<br />
        &lt;div class="divHeader" id="masthead"&gt;<br />
            This is the header<br />
        &lt;/div&gt;<br />
        &lt;div id="divPlaceHolderWrapper"&gt;<br />
            &lt;asp:ContentPlaceHolder
id="ContentPlaceHolder1" runat="server" /&gt;<br />
        &lt;/div&gt;<br />
    &lt;/form&gt;<br />
&lt;/body&gt;
</div>
        <p>
Your CSS should look like this:
</p>
        <div class="divCodeBlock">body, html {<br />
    overflow: hidden;<br />
    font-family: Arial, Sans-Serif;<br />
    margin: 0;<br />
} 
<br /><br />
.divHeader {<br />
    background-color: Gray; 
<br />
    color:White;<br />
    font-size: 2em;<br />
    font-weight: bold;<br />
} 
<br /><br />
#divPlaceHolderWrapper {<br />
    overflow: auto;    
<br />
}
</div>
        <p>
Hiding the overflow for the HTML has the effect of removing the scrollbar from the
browser window.  We add it back to our div 
</p>
        <p>
And you'll need this JavaScript (<a title="JavaScript Source" href="http://p2p.wrox.com/topic.asp?TOPIC_ID=5087" target="_blank">which
I found here</a>):
</p>
        <div class="divCodeBlock">&lt;script language="javascript" type="text/javascript"&gt;<br />
    function GetWindowHeight() {<br />
        var myHeight = 0;<br />
        if( typeof( window.innerWidth ) == 'number'
){ 
<br />
            //Non-IE<br />
            myHeight = window.innerHeight;<br />
        }<br />
        else {<br />
            if ( document.documentElement
&amp;&amp; ( document.documentElement.clientWidth ||    document.documentElement.clientHeight
) ){ 
<br />
               
//IE 6+ in 'standards compliant mode'<br />
               
myHeight = document.documentElement.clientHeight;<br />
            }<br />
            else {<br />
               
if ( document.body &amp;&amp; ( document.body.clientWidth || document.body.clientHeight
) ) { 
<br />
                   
//IE 4 compatible<br />
                   
myHeight = document.body.clientHeight;<br />
               
}<br />
            }<br />
        }<br />
        return myHeight;    
}<br />
    function SetPlaceHolderWrapperHeight() {<br />
        var wrapperHeight = GetWindowHeight() -
37;  //the height of the lower edge of the browser window<br />
        document.getElementById('divPlaceHolderWrapper').style.height
= wrapperHeight + 'px';<br />
    }    
<br />
    window.onload = function() { SetPlaceHolderWrapperHeight(); } 
<br />
    window.onresize = function() { SetPlaceHolderWrapperHeight(); } 
<br />
&lt;/script&gt; 
</div>
        <p>
The resulting page will show the contents of the divPlaceHolderWrapper (in this case
- whatever is in the content area of the page using this MasterPage) with a scrollbar
if necessary.  If the content does not fill up the window, then no scrollbar
appears.  While resizing the browser window in IE divPlaceHolderWrapper is continuously
resized.  In Firefox the div is resized once the resizing of the browser window
is complete.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=7deb9537-7840-44c2-9ebd-0cb71ab27e2d" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Adventures of a Lead Programmer in a One-man Shop: Episode 4 - MSBuild Script</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/05/27/AdventuresOfALeadProgrammerInAOnemanShopEpisode4MSBuildScript.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,14802b9d-f090-46f3-8c1f-773b10fda12f.aspx</id>
    <published>2008-05-27T15:13:28.306-07:00</published>
    <updated>2008-05-28T04:22:17.322375-07:00</updated>
    <category term="Continuous Integration" label="Continuous Integration" scheme="http://thirstycrow.net/blog/CategoryView,category,ContinuousIntegration.aspx" />
    <category term="MSBuild" label="MSBuild" scheme="http://thirstycrow.net/blog/CategoryView,category,MSBuild.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
In the last episode I covered the installation of TeamCity and the associated MySQL
database and said I would cover the configuration next.  I'm going to put that
off for now and instead focus on MSBuild and the associated build script.  
</p>
        <p>
Within TeamCity there are several available build runners.  From the TeamCity
documentation a build runner is "<a href="http://www.jetbrains.net/confluence/display/TCD3/Build+Runner" target="_blank">a
mechanism that executes a build of a certain type</a>."  That's vague way of
saying it will do the same thing that choosing "Build Solution" from the Build menu
in Visual Studio will do - an oversimplification perhaps, but true.  So what's
going on under the hood?  In this case, Visual Studio uses the settings in your
solution and project files to compile your application or class library whether it
be a debug or release build.  That is to say - the build script (a solution file)
directs the actions of the build runner (Visual Studio).
</p>
        <p>
TeamCity supports <a href="http://www.jetbrains.net/confluence/display/TCD3/3.Build+Runners" target="_blank">a
dozen build runners</a>, among which are sln2005, sln2008, and MSBuild.  The
TeamCity documentation says to choose sln2005 or sln2008 if you want to use your .sln
file from Visual Studio 2005 or 2008 respectively as the build script.  I started
off down that track but quickly realized that I needed more control than I could get
with a .sln file so I switched to MSBuild and used an MSBuild script.  In truth
sln2005 uses MSBuild from .Net 2.0 while sln2008 uses the version of MSBuild from
.Net 3.5.  The practical differences are in the configuration screens in the
TeamCity setup.  For now, just be aware that MSBuild comes as part of the .Net
framework installation.  You'll find it on your machine at &lt;system drive&gt;\Windows\Microsoft.NET\Framework\&lt;version&gt;\MSBuild.exe. 
You can see it in action by opening a Visual Studio command prompt (Programs &gt;
Microsoft Visual Studio&gt; Visual Studio Tools &gt; Visual Studio 2008 Command Prompt)
and entering the command msbuild followed by the full path to a .sln file.  Hit
return and you'll see the build process.  It's the same thing that happens when
you build from inside Visual Studio itself.    
</p>
        <p>
As I mentioned earlier, MSBuild can use solution (.sln) files as build scripts although
they do not have the same format as a true MSBuild project file.  Visual Studio
project files do follow the format though. You can open one in NotePad to see the
structure.  To get the whole thing started though you'll need a project file. 
Start with something like this:
</p>
        <div class="divCodeBlock">&lt;Project DefaultTargets="" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;<br />
&lt;/Project&gt;
</div>
        <p>
I called mine BuildScipt.xml and used Visual Studio for editing.  You might prefer
the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=72d6aa49-787d-4118-ba5f-4f30fe913628&amp;displaylang=en" target="_blank">XML
Notepad tool from Microsoft</a>.  As for the contents, <a href="http://msdn.microsoft.com/en-us/library/ms171452.aspx" target="_blank">MSDN
has an overview of the file format</a> for your reference.  In summary, there
are several distinct sections:
</p>
        <p>
          <strong>PropertyGroup</strong>: Contains key/value pairs that can be referenced elsewhere
in the script
</p>
        <div class="divCodeBlock">&lt;PropertyGroup&gt;<br />
    &lt;TextResources&gt;$(MSBuildProjectDirectory)\textfiles&lt;/TextResources&gt;<br />
    &lt;SourceControlUserName&gt;bobsuruncle&lt;/SourceControlUserName&gt;<br />
&lt;/PropertyGroup&gt;
</div>
        <p>
The $(MSBuildProjectDirectory) notation above uses a <a href="http://msdn.microsoft.com/en-us/library/ms164309.aspx" target="_blank">reserved
word</a>.  MSBuildProjectDirectory refers to the directory that contains the
build script.  The TextResources key (one of my own making) above refers to a
directory named "textfiles" that is within the directory containing the build script
itself.  The $() notation is used to invoke a reserved word and is also used
to reference the value of a PropertyGroup element via its key (see below).
</p>
        <p>
          <strong>ItemGroup</strong>: Contains references to inputs into the build
</p>
        <div class="divCodeBlock">&lt;ItemGroup&gt;<br />
    &lt;FilesToInclude="$(TextResources)\readme.txt" /&gt;<br />
    &lt;FilesToInclude="$(TextResources)\license.doc" /&gt;<br />
&lt;/ItemGroup&gt;
</div>
        <p>
Notice that in the "FilesToInclude" item group there are two files, readme.txt and
license.doc.  They are found using the path described by the TextResources PropertyGroup
element.  It is therefore equivalent to ".\textfiles\".  Later we can use
@ character instead of $ (i.e., @(FilesToInclude)) to refer to this entire list of
elements (see below).  
</p>
        <p>
          <strong>Target</strong>: Groups of tasks to be performed as a unit.  
</p>
        <div class="divCodeBlock">&lt;Target Name="CleanProject"&gt;<br />
  &lt;Message Text="******** Beginning Cleaning ********" /&gt;<br />
  &lt;!-- delete the InstallerComponentDirectory directory and its contents --&gt;<br />
  &lt;RemoveDir Directories="$(InstallerComponentDirectory)" /&gt; 
<br />
  &lt;!-- delete the InstallerOutputDirectory directory and its contents --&gt;<br />
  &lt;RemoveDir Directories="$(InstallerOutputDirectory)" /&gt; 
<br />
  &lt;!-- clean the build --&gt;<br />
  &lt;MSBuild Projects=".\MySolution.sln" Targets="Clean" ContinueOnError="false"
/&gt;<br />
  &lt;Message Text="******** Cleaning Complete ********" /&gt; 
<br />
&lt;/Target&gt;
</div>
        <p>
This section introduces a few more concepts.  The name attribute is how you refer
to the target elsewhere in the script.  Comments are designated with &lt;!--
--&gt; notation.  The Messages element is a <a href="http://msdn.microsoft.com/en-us/library/7z253716.aspx" target="_blank">preconfigured
MSBuild task</a> similar to Console.WriteLine() command for outputting information
to the screen.  You will see this output while watching a build in TeamCity (as
well as in the build log) so it makes for useful real-time feedback during the process. 
The RemoveDir and MSBuild elements are also MSBuild tasks.  The <a href="http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx" target="_blank">MSBuild
task</a> is used to run the "Clean" command on the solution via the Targets attribute. 
I could have just as easily put "release" or "debug" to run those builds.  In
addition to the tasks that ship with MSBuild you can also make use of <a href="http://msbuildtasks.tigris.org/" target="_blank">MSBuild
Community Tasks</a> which expands your options to include creating assembly files,
FTP support, zip compression, registry manipulation, and more.  MSBuild Community
Tasks is an open source project available as both an installer and source code. 
Download the source code even if you don't need it because it includes the documentation
as a help file.  If you get that annoying "Navigation to webpage was canceled"
error when you open the help file remember to right-click on the file, choose properties
from the context menu, and then click the Unblock button on the General tab to restore
functionality.  To make use of the tasks run the MSBuild Community Tasks installer
then add the following line just after the opening tag of your build script: 
</p>
        <div class="divCodeBlock">&lt;Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/&gt;
</div>
        <p>
For my HappyFish build script I wanted to be able to upload my changes to source control
and with no other interaction end up with an installer on my Web site with the version
number in the file name (i.e., HappyFish.2.0.63.117.msi).  The steps involved
break down to: 
</p>
        <ol>
          <li>
Create the assembly file(s) for the dll's and the exe to handle versioning 
</li>
          <li>
Compile the solution 
</li>
          <li>
Merge the assemblies 
</li>
          <li>
Create the installer 
</li>
          <li>
FTP the results</li>
        </ol>
        <p>
The hardest part was dealing with the build number.  I tried a lot of different
techniques for tracking and managing build number incrementing but finally decided
the least amount of friction was to let TeamCity handle it for me.  I'll have
more on this in a later post, but TeamCity allows you to specify the build number
format and seed for the build count value.  You can then refer to the build number
using "$(build_number)" <a href="http://www.jetbrains.net/confluence/display/TCD3/System+Properties+of+a+Build+Configuration" target="_blank">environment
variable</a> in your script wherever you need it.  
</p>
        <p>
Returning to the list, step one consisted of making Assembly.cs files for the project
components like so:
</p>
        <div class="divCodeBlock">&lt;Target Name="SomeComponentAssembly" &gt;<br />
  &lt;Message Text="Writing SomeComponentAssembly file for $(build_number)"/&gt;<br />
  &lt;!-- Create/update the assembly.cs file --&gt;<br />
  &lt;AssemblyInfo CodeLanguage="CS"<br />
   OutputFile="$(ProjectDirectory)\MyProject\Properties\AssemblyInfo.cs"<br />
   AssemblyTitle="MyProject.MyAssembly"<br />
   AssemblyDescription="My Project Library"<br />
   AssemblyConfiguration=""<br />
   AssemblyCompany="ThirstyCrow"<br />
   AssemblyProduct="ThirstyCrow.MyProject.MyAssembly"<br />
   AssemblyCopyright="Copyright © ThirstyCrow 2008"<br />
   AssemblyTrademark="thirstycrow.net"<br />
   ComVisible="false"<br />
   CLSCompliant="true"<br />
   Guid="9cd1823a-7c8f-4a0c-b740-0311ec695afe"<br />
   AssemblyVersion="$(build_number)"<br />
   AssemblyFileVersion="$(build_number)" /&gt;<br />
&lt;/Target&gt;
</div>
        <p>
Complete documentation of the Assembly task can be found in the MSBuild help file
by searching for assemblyinfo class members.  If want a quick way to create Guids <a href="http://goatly.spaces.live.com/Blog/cns!ED869F22AB5C24A8!182.entry" target="_blank">check
out this tip</a>.
</p>
        <p>
Second on the list is to compile the solution.  This is easily done with the
MSBuild task show above.  By specifying that the StartMyBuild task below depends
on another target, in this case SomeComponentAssembly then the tasks within that target
will be run before the StartMyBuild tasks.  If you have more than one dependency
you can enter them as a semicolon separated string (i.e., "SomeComponentAssembly;SomeOtherComponentAssembly;YetAnotherComponentAssembly" 
</p>
        <div class="divCodeBlock">&lt;Target Name="StartMyBuild" DependsOnTarget="SomeComponentAssembly"&gt;<br />
  &lt;MSBuild Projects=".\MySolution.sln" Targets="Rebuild" ContinueOnError="false"
/&gt;<br />
  &lt;Message Text="******** Build Complete ********" /&gt;<br />
&lt;/Target&gt;
</div>
        <p>
You may or may not want to merge your assemblies, but if so you can use the ILMerge
class of the MSBuild Community Tasks.  In the example below I've used the MakeDir
MSBuild task to conditionally make a directory that will be used later to hold all
of the components that will be combined into an installer project.  ILMerge is
used to merge the list of components found in the "MergeFiles" ItemGroup.  NOTE:
For some reason that I have yet to figure out if you use the $(propertygroup) notation
in the OutputFile attribute of ILMerge it will fail so you'll have to put in the path
explicitly.  However, it can be a relative path as shown.  Finally, as part
of this target I've copied the supporting documents from the FilesToInclude (see above)
- the readme and license documents - to the InstallerComponentDirectory that I'll
be using later.
</p>
        <div class="divCodeBlock">&lt;Target Name="MergeAssemblies" &gt;<br />
  &lt;Message Text="******** Beginning Merge ********" /&gt;<br />
  &lt;!-- create the InstallerComponentDirectory directory --&gt;<br />
  &lt;MakeDir Directories="$(InstallerComponentDirectory)" Condition="!Exists('$(InstallerComponentDirectory)')"/&gt; 
<br />
  &lt;!-- merge the assemblies --&gt;<br />
  &lt;ILMerge TargetKind="WinExe" OutputFile=".<strong><em>Installer\ComponentDirectory</em></strong>\MyApplication.exe"
InputAssemblies="@(MergeFiles)" DebugInfo="false"/&gt; 
<br />
  &lt;!-- copy the files to the InstallerComponentDirectory directory --&gt;<br />
  &lt;Copy SourceFiles="@(FilesToInclude)" DestinationFolder="$(InstallerComponentDirectory)"
/&gt; 
<br />
  &lt;Message Text="******** Merge Complete ********" /&gt;<br />
&lt;/Target&gt; 
</div>
        <p>
For the installer I used <a href="http://wix.sourceforge.net/" target="_blank">Wix</a>,
which warrants a post or two of its own.  I'll skip over that for now and move
on to FTP.  FTP is straight forward, just follow the documentation in the MSBuild
Community Tasks found under FtpUpload Class.  My section looked something like
this:
</p>
        <div class="divCodeBlock">&lt;Target Name="FtpProject"&gt;<br />
  &lt;Message Text="******** Uploading Files ********" /&gt;<br />
  &lt;FtpUpload 
<br />
    Username="myusername"<br />
    password="mypassword"<br />
    RemoteUri="ftp://mydomain.com/builds/MyApplication.$(build_number).msi"<br />
    LocalFile="$(InstallerOutputDirectory)\MyApplication.msi" /&gt;<br />
  &lt;Message Text="******** Uploading Complete ********" /&gt;<br />
&lt;/Target&gt;
</div>
        <p>
You'll notice I made use of the build number environment variable provided by TeamCity
to differentiate this build from others, thereby preventing naming collisions. 
</p>
        <p>
To test your build script you'll need a way to get the whole thing started. 
Use the DefaultTargets attribute of the opening Project tag to tell MSBuild where
to start.  Based on the example above I might use DefaultTargets="StartMyBuild". 
This list can also be a semicolon separated list such as DefaultTargets="StartMyBuild;MergeAssemblies;FtpProject". 
Save your changes and bring up the Visual Studio command prompt (see above) and run
msbuild &lt;path to your script&gt;.  Be aware of the following caveats in troubleshooting:
</p>
        <ul>
          <li>
References to the TeamCity specific $(build_number) environment variable will be empty
strings, but it will not cause the script to fail.  The FtpProject output to
the remote server would consequently be MyApplication..msi.  In production the
space between the two dots in the filename would contain the build number. 
</li>
          <li>
If you use the copyright symbol © you'll need to make sure that the encoding of you
build script is UTF-8.</li>
        </ul>
        <p>
At this point, if the script runs from the Visual Studio command prompt and you've
used relative directory paths based on the MSBuildProjectDirectory reserved word you
should be in good shape for using this script with TeamCity.  That will be the
topic of the next thrilling episode of Adventures of a Lead Programmer in a One-man
Shop.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=14802b9d-f090-46f3-8c1f-773b10fda12f" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Adventures of a Lead Programmer in a One-man Shop: Episode 3 - Continuous Integration</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/04/29/AdventuresOfALeadProgrammerInAOnemanShopEpisode3ContinuousIntegration.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,5cdd334f-1afa-48c1-b9cd-715dc052087d.aspx</id>
    <published>2008-04-29T09:12:45.241625-07:00</published>
    <updated>2008-04-29T09:12:45.241625-07:00</updated>
    <category term="Continuous Integration" label="Continuous Integration" scheme="http://thirstycrow.net/blog/CategoryView,category,ContinuousIntegration.aspx" />
    <category term="Source Control" label="Source Control" scheme="http://thirstycrow.net/blog/CategoryView,category,SourceControl.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <blockquote>
          <p>
            <em>Previously on Adventures of a Lead Programmer in a One-man Shop -<br />
"No, please, I can't take it anymore.  I'll do it.  I'll put my code in
source control.  I can't bear the .zip file shame any longer.  Just leave
me enough money for milk and crackers.  What?  It's free?!?  And easy?!? 
You had me at free..."</em>
          </p>
        </blockquote>
        <p>
It's official.  I've begun wriggling out of my inferiority complex and scrambling
up toward a shinny, new Superiority Complex.  In my <a href="http://thirstycrow.net/blog/2008/04/25/AdventuresOfALeadProgrammerInAOnemanShopEpisode2SourceControl.aspx" target="_blank">previous
post</a> I said that I wanted to couple my source control solution to a <a href="http://www.martinfowler.com/articles/continuousIntegration.html" target="_blank">Continuous
Integration</a> server that will compile my latest <strike>bugs</strike> edits into
a software release.  When researching continuous integration solutions the two
that I heard mentioned most often were <a href="http://cruisecontrol.sourceforge.net/" target="_blank">CruiseControl.NET</a>,
an open source project from <a href="http://www.thoughtworks.com/" target="_blank">ThoughtWorks</a>,
and <a href="http://www.jetbrains.com/teamcity" target="_blank">TeamCity</a> from <a href="http://www.jetbrains.com/" target="_blank">JetBrains</a>. 
CC.NET is free and JetBrains offers a free professional version so they both passed
the first test.  My sense from snooping around on the web though was that TeamCity
would be easier to configure.  I can't say if TeamCity was easier than CC.NET
because I didn't try both, but I can say that TeamCity was easy.  There were
a couple of points I found confusing though.  I've detailed them in the guide
below.  I went through the actual setup twice, but if you find any errors to
fix or tips to add please let me know.  
</p>
        <p>
This guide is intended to be used in conjunction with the <a href="http://www.jetbrains.net/confluence/display/TCD3/TeamCity+Documentation;jsessionid=92CB84FCFFFC5F6342AB5838152C79AC" target="_blank">TeamCity
documentation</a>.  I have included the relevant links below.  The guide
covers installation of TeamCity and installation and configuration of MySQL (also
free, of course) to serve as a back end for TeamCity.  For completeness I've
included the Subversion setup steps at the beginning.  Refer to <a href="http://polymorphicpodcast.com/shows/subversion/" target="_blank">Craig
Shoemaker's Subversion episode</a> for more details.  On the first run through
I set up TeamCity on an instance of Windows 2003 running locally on <a href="http://technet.microsoft.com/en-us/bb738033.aspx" target="_blank">Virtual
Server 2005 R2</a>.  The second setup was on a remote Windows 2003 server that
will be used for production.  Windows 2003 is not a requirement.  All of
this can be configured on a single machine (i.e., your desktop machine).  
</p>
        <ol>
          <li>
Installed Subversion using <a href="http://svn1clicksetup.tigris.org/" target="_blank">SVN
1-Click Setup</a> option. NOTE: During the install I skipped the Tortoise installation
step because the bundled version is not the most current. 
</li>
          <li>
Installed the <a href="http://tortoisesvn.net/downloads" target="_blank">current version
of Tortoise</a>. 
</li>
          <li>
Installed <a href="http://www.jetbrains.com/teamcity/download/" target="_blank">TeamCity
3.1 Profession Edition</a> following their <a href="http://www.jetbrains.net/confluence/display/TCD3/Installation+and+Upgrade" target="_blank">installation
documentation</a>. 
<ul><li>
During the setup I chose 8080 as the port because I already had IIS installed using
port 80. 
</li><li>
For the rest of the installation I clicked through, accepting all of the defaults
including for the Build Configuration dialog at the end. 
</li><li>
Logged in for the first time to accept the license agreement and create the administrative
account.</li></ul></li>
          <li>
Setup MySQL for TeamCity following <a href="http://www.jetbrains.net/confluence/display/TCD3/Setting+up+an+External+Database" target="_blank">their
documentation</a>. 
<ul><li>
Downloaded <a href="http://dev.mysql.com/downloads/" target="_blank">MySQL Community
Server</a>.  I chose the default typical installation type. 
</li><li>
At the end of the installation when prompted with the database configuration I chose
Detailed Configuration.  
</li><li>
I accepted the defaults until I reached the Concurrent Connections option.  I
chose Manual Setting and set the value to 5.  Nothing magical, I just picked
the lowest one since I'll only be using this for TeamCity.  You can also manually
enter any number. 
</li><li>
On the Default Character Set option page of the wizard I chose the Manual option and
set the value to utf8, as suggested in the TeamCity docs.  
</li><li>
On the security screen I checked the box to allow remote access. 
</li><li>
I accepted the default settings on the rest of the pages in the setup wizard. 
</li><li>
If you make a mistake or want to change the settings later the configuration wizard
can be accessed from the start menu (Programs &gt; MySQL &gt; MySQL Server 5.0 &gt;
MySQL Server Instance Configuration Wizard).</li></ul></li>
          <li>
Downloaded and installed <a href="http://www.webyog.com/en/downloads.php" target="_blank">SQLyog
MySQL GUI - Community Edition</a>.  Yep, it's free.  I've used it before
and recommend it.  This will be used to create and manage databases in your installation
of MySQL.  
<ul><li>
After installation <a href="http://thirstycrow.net//blog/content/postimages/teamcitymysqlconfig/initialmysqlconnection.jpg" target="_blank">I
connected to my instance of MySQL</a> with SQLyog using the root credentials that
I specified in the setup. 
</li><li>
I <a href="http://thirstycrow.net//blog/content/postimages/teamcitymysqlconfig/createdatabasedialog.jpg" target="_blank">created
a new database</a> for use with TeamCity (DB &gt; Create Database).  I named
it...wait for it... TeamCity and set the character set to utf8. 
</li><li>
I used the User Manager of SQLyog to create an account on the MySQL instance under
which TeamCity will access the database.  The User Manager is found in the Tools
menu or by clicking the User Manager button on the toolbar.  I set the account
name to...you guessed it... teamcityuser and <a href="http://thirstycrow.net//blog/content/postimages/teamcitymysqlconfig/mysqlaccountdialog.jpg" target="_blank">granted
full permissions</a> because at the time I had no idea which privileges were necessary. 
Certainly it will need Select, Insert, Update, Delete, and Create to create the supporting
tables.  I wasn't sure if it would need Drop, Alter, and Grant for the setup
as well.  I'll restrict them later once I've got everything working.  
</li><li>
At this point I connected to my instance of MySQL using the new credentials to verify
everything was working.  If you're following along notice that the tables directory
in the newly created teamcity database is empty.</li></ul></li>
          <li>
Downloaded and configured the <a href="http://dev.mysql.com/downloads/connector/j/5.1.html" target="_blank">MySQL
JDBC driver</a>.  The JDBC driver allows TeamCity to connect to the MySQL database. 
<ul><li>
The TeamCity documentation says to put the MySQL connector jar in the WEB-INF/lib
of TeamCity's web application.  The MySQL connector jar file name is mysql-connector-java-5.1.6-bin.jar
and is found at the root of the unzipped directory.  I copied it to C:\TeamCity\webapps\ROOT\WEB-INF\lib
of my installation.  
</li><li>
The next step is to modify the database.mysql.properties file which is found in the
C:\Documents and Settings\&lt;<em>account name</em>&gt;\.BuildServer\config directory. 
Before renaming and modifying the file as directed in the setup I made a copy of the
file as a backup.  I opened the renamed file in notepad and made the following
changes: 
<ol><li>
connectionUrl=jdbc:mysql://localhost/<em><strong>teamcity</strong></em></li><li>
connectionProperties.user=<em><strong>teamcityuser</strong></em></li><li>
connectionProperties.password=<em><strong>the password I chose</strong></em></li><li>
uncommented the connectionProperties.characterEncoding=UTF-8 line by removing the
leading # character</li></ol></li><li>
Saved the changes and closed the file.  
</li></ul></li>
        </ol>
        <p>
After making the changes I restarted the server.  I opened a web browser on the
server and navigated to localhost:8080.  I was prompted to accept the license
agreement again and had to recreate the administration account because the old local
data store had now been successfully replaced with MySQL.  You'll also notice
at this point if you've followed along that SQLyog will show the supporting tables
have been created in the database you made for TeamCity.
</p>
        <p>
Now what?  
</p>
        <p>
Next I need to configure TeamCity to automatically perform a build of the code from
my source control repository.  I'll cover that in the next thrilling Adventure
of a Lead Programmer in a One-Man Shop.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=5cdd334f-1afa-48c1-b9cd-715dc052087d" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Adventures of a Lead Programmer in a One-man Shop: Episode 2 - Source Control</title>
    <link rel="alternate" type="text/html" href="http://thirstycrow.net/blog/2008/04/25/AdventuresOfALeadProgrammerInAOnemanShopEpisode2SourceControl.aspx" />
    <id>http://thirstycrow.net/blog/PermaLink,guid,49293ae4-bee0-46c4-961f-6840ffcd1ff8.aspx</id>
    <published>2008-04-25T10:00:07-07:00</published>
    <updated>2008-04-22T14:48:10.119375-07:00</updated>
    <category term="Source Control" label="Source Control" scheme="http://thirstycrow.net/blog/CategoryView,category,SourceControl.aspx" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
Good gravy, people.  Why didn't you tell me is was this easy to use source control? 
Leave it to <a href="http://polymorphicpodcast.com/about/">Craig Shoemaker</a> and
his <a href="http://polymorphicpodcast.com/" target="_blank">Polymorphic Podcast</a> to,
as Denzel Washington's character in <a href="http://www.imdb.com/title/tt0107818/" target="_blank">Philadelphia</a> said,
"Explain it to me like I'm a four-year-old."  I listened to his series on <a href="http://polymorphicpodcast.com/shows/mv-patterns/" target="_blank">Design
Patterns</a> in March of 2007 and it was a revelation.  He produced a show in
August of last year called <a href="http://polymorphicpodcast.com/shows/subversion/" target="_blank">Subversion
Quickstart for .NET Developers</a> that I didn't listen to at the time but made a
mental note to go back to.  I'm embarrassed to say this, but up to this point
I've been using .zip files as my caveman-esque source control system.  In my
defense though, it's not like I didn't know what source control was or have access
to it.  Visual Source Safe has been available to me for several years. 
However, based on everything I'd heard a better alternative would be to print out
my code and hide the reams of paper under my mattress.  So here I've been with
a growing pile of .zip files and an inferiority complex.  The reason I finally
returned to the topic was the browbeating I was getting from magazine articles I've
been reading about Agile Programming methods.  "You are using source control,
aren't you?", they asked.  I nodded, made up an excuse about having to go turn
off my headlights, and pulled up Craig's Quickstart.  It was just what I expected
- he made it crazy easy.  
</p>
        <p>
The next question was how can I apply this to my day job?  I knew setting up
a source control solution for work would be easy.  I've got access to all the
servers I would need for that.  But what about HappyFish?  Whatever I found
I wanted it to be:
</p>
        <ul>
          <li>
On a remote site for easy access 
</li>
          <li>
Trustworthy with respect to backups and security 
</li>
          <li>
Free for closed source projects</li>
        </ul>
        <p>
          <a href="http://sourceforge.net/" target="_blank">SourceForge</a> would probably have
been the answer if not for the closed source requirement, but I'm not ready to open
HappyFish yet.  My hosting provider seemed like a good place to start. 
I use <a href="http://www.WebHost4Life.com/default.asp?refid=argiope" target="_blank">webhost4life</a>. 
I've heard good things about other hosts, and even tried one, but no other host gives
the same level of features that they offer for the price.  And no other host
provides as much user control over their set up in a shared hosting environment. 
(If you sign up for their hosting and <a href="http://www.WebHost4Life.com/default.asp?refid=argiope" target="_blank">start
with this link</a> then I'll get a credit toward my hosting.  Many thanks.)  
At any rate, I checked with them and they don't offer a free source control solution. 
Undaunted, I searched on and eventually found <a href="http://unfuddle.com" target="_blank">Unfuddle</a>. 
This is another one of those mysteries of the web - 200MB of free, secure, closed
source control hosting space.  
</p>
        <p>
There you have it - from .zip files to true source control in zero dollars. 
Thanks Craig.  Thanks Unfuddle.  But it doesn't stop there.  This whole
mess started with me reading articles about agile programming techniques.  What
good is source control with out a continuous integration solution to go along with
it?  I found a free solution for that too.  I'll tell you all about it in
the next episode.
</p>
        <img width="0" height="0" src="http://thirstycrow.net/blog/aggbug.ashx?id=49293ae4-bee0-46c4-961f-6840ffcd1ff8" />
      </div>
    </content>
  </entry>
</feed>