<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>crunchlife: Tag dotNET</title>
    <link>http://crunchlife.com/articles/tag/dotnet</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Yet Another Join Method</title>
      <description>&lt;p&gt;The .NET String type has a &lt;a href="http://msdn.microsoft.com/en-us/library/57a79xd0.aspx" target="_blank"&gt;Join method&lt;/a&gt;, but in my latest ASP.NET project I had the need for joining String array elements with additional prefix and suffix values. The method below delimits array elements with the provided separator and concatenates the elements with the prefix and suffix string parameters.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve found this particularly handy when creating SQL statements that require the IN keyword.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;string[] names = { &amp;quot;Bobby&amp;quot;, &amp;quot;Suzy&amp;quot; };

sql += &amp;quot;WHERE People.FirstName IN (&amp;quot; + Utility.Join(&amp;quot;,&amp;quot;, names, &amp;quot;'&amp;quot;, &amp;quot;'&amp;quot;) + &amp;quot;)&amp;quot;;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add this method to your utility class or extended String type.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public static string Join(string separator, string[] value, string
prefix, string suffix)
{
    string toReturn = String.Empty;

    int i;
    for (i = 0; i &amp;lt; value.Length; i++)
    {
        if (i != value.Length - 1)
            toReturn += prefix + value[i] + suffix + separator;
        else
            toReturn += prefix + value[i] + suffix;
    }

    return toReturn;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 12 Sep 2008 14:27:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:05392c66-db31-4f67-80a6-e73740c41523</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/09/12/yet-another-join-method</link>
      <category>Code Snippets</category>
      <category>CSharp</category>
      <category>dotNET</category>
    </item>
    <item>
      <title>Removing Duplicate Items from an Abstract Generic List</title>
      <description>&lt;p&gt;&lt;img src="/files/rocking_chair.jpg" class="right" /&gt;I&amp;#8217;ve got some explaining to do. I
was hesitant in posting this code for fear that it might be too niche
to benefit anyone. It may be, but the underlying problem affects many
programmers working in the IT industry. What do you do when the company
legacy system&amp;#8217;s data model doesn&amp;#8217;t work with your fancy &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping" target="_blank"&gt;ORM (Object-relational mapping)&lt;/a&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&amp;#8220;Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem.&amp;#8221; - &lt;a href="http://en.wikipedia.org/wiki/David_Wheeler_(computer_scientist)" target="_blank"&gt;David Wheeler&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;At my last job, the &lt;a href="http://en.wikipedia.org/wiki/Enterprise_resource_planning" target="_blank"&gt;ERP (Enterprise resource planning)&lt;/a&gt; system was something of mystery and voodoo. Only a few had sufficient knowledge to work with it and because of its arcane nature it was deemed untouchable. Within my first months as an employee I wrote a rudimentary ORM to serve as a layer between our client applications and the ERP system. Its performance was terrible. I wrote it off as &amp;#8220;experience&amp;#8221; and the department ultimately decided to ignore interfacing directly with the ERP system.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m using the &lt;a href="http://subsonicproject.com/" target="_blank"&gt;SubSonic&lt;/a&gt; ORM on a few ASP.NET projects with my current employer. SubSonic has worked great, but a
few of its database requirements have left me in the dust with yet another ERP system. The ERP&amp;#8217;s tables have no primary keys, constraints, or relationships, but rather than write a complete ORM I decided to roll my own data layer.&lt;/p&gt;

&lt;p&gt;All of the strongly-typed collections in the ERP&amp;#8217;s data layer implement the AbstractList type. AbstractList implements List&lt;ItemType&gt; where ItemType implements IUniqueIdentifier. That is a mouthful, but the key (pun intended) to removing duplicate items is to make sure they&amp;#8217;re unique.&lt;/p&gt;

&lt;p&gt;The IUniqueIdentifier interface contains only one property, UniqueIdentifier.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public interface IUniqueIdentifier
{
    string UniqueIdentifier
    {
        get;
        set;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 

&lt;p&gt;If the ERP system contained a table called Customers a Customer type implementing IUniqueIdentifier would be created. &lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public class Customer : IUniqueIdentifier
{
    private string uniqueIdentifier;

    // etc...

    public UniqueIdentifier
    {
        get { return this.uniqueIdentifier; }
        set { this.uniqueIdentifier = value; }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I&amp;#8217;d also have a CustomerCollection class:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public class CustomerCollection : AbstractList&amp;lt;Customer, CustomerCollection&amp;gt;
{
    // etc...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After such a long-winded introduction I can feel better about dumping the following code on anyone that has happened to read this far (kudos to you).&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public abstract class AbstractList&amp;lt;ItemType, ListType&amp;gt; :
List&amp;lt;ItemType&amp;gt; where ItemType:IUniqueIdentifier where
ListType:AbstractList&amp;lt;ItemType, ListType&amp;gt;, new()
{
    public ListType RemoveDuplicates()
    {
        Dictionary&amp;lt;string, int&amp;gt; uniqueStore = new Dictionary&amp;lt;string, int&amp;gt;();
        ListType list = new ListType();

        foreach (ItemType item in this)
        {
            if (!uniqueStore.ContainsKey(item.UniqueIdentifier))
            {
                uniqueStore.Add(item.UniqueIdentifier, 0);
                list.Add(item);
            }
        }

        return list;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I&amp;#8217;d love to hear how others have worked around legacy systems and still kept their code clean. &lt;/p&gt;</description>
      <pubDate>Thu, 31 Jul 2008 07:40:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:f418da7f-eb68-46f7-9192-6c8254e39b4f</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/07/31/removing-duplicate-items-from-an-abstract-generic-list</link>
      <category>Code Snippets</category>
      <category>Expect the Unexpected</category>
      <category>CSharp</category>
      <category>dotNET</category>
      <category>ORM</category>
      <enclosure type="image/jpeg" length="61497" url="http://crunchlife.com/files/rocking_chair.jpg"/>
      <trackback:ping>http://crunchlife.com/articles/trackback/75</trackback:ping>
    </item>
    <item>
      <title>Temporary Identity Impersonation in ASP.NET</title>
      <description>&lt;p&gt;Uploading files in an ASP.NET application is relatively easy to do. Uploading to a remote machine is a little bit trickier, but certainly doable. I followed a &lt;a href="http://aspalliance.com/336_Upload_Files_Using_ASPNET_Impersonation_and_UNC_Share.all" target="_blank"&gt;set of instructions&lt;/a&gt; on aspalliance.com, but rather than declare an account to impersonate in my web.config file, I decided to do it in code. That way I could use impersonation only when needed and encapsulate it for later use.&lt;/p&gt;

&lt;p&gt;I referred to an &lt;a href="http://support.microsoft.com/kb/306158#4" target="_blank"&gt;article&lt;/a&gt; on Microsoft&amp;#8217;s Help and Support website about how to implement impersonation. Their code worked great, but I decided to put it in a class to help keep things &lt;a href="http://en.wikipedia.org/wiki/DRY" target="_blank"&gt;DRY&lt;/a&gt;.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;using System;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace Utilities
{    
    public class ImpersonateUser
    {
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        WindowsImpersonationContext impersonationContext;

        [DllImport(&amp;quot;advapi32.dll&amp;quot;)]
        public static extern int LogonUserA(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
        [DllImport(&amp;quot;advapi32.dll&amp;quot;, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);

        [DllImport(&amp;quot;advapi32.dll&amp;quot;, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport(&amp;quot;kernel32.dll&amp;quot;, CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public bool ImpersonateValidUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        }

        public void UndoImpersonation()
        {
            impersonationContext.Undo();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After referencing my Utilities namespace I was then able to impersonate the account required for uploading:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;if (FileUpload1.HasFile)
{
    ImpersonateUser impersonateUser = new ImpersonateUser();

    if (impersonateUser.ImpersonateValidUser(&amp;quot;userName&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;password&amp;quot;))
    {
        FileUpload1.SaveAs(Server.MapPath(&amp;quot;~/files/fileName.txt&amp;quot;));
        impersonateUser.UndoImpersonation();
    }
    else
    {
        throw new Exception(&amp;quot;Identity impersonation has failed.&amp;quot;);
    }   
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;*The SaveAs method of the FileUpload control requires a root path. Using Server.MapPath will provide the root path of your IIS virtual folder.&lt;/strong&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 27 May 2008 09:01:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:9aea73ef-a3d1-4208-9128-12eb032da707</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/05/27/temporary-identity-impersonation-in-asp-net</link>
      <category>Code Snippets</category>
      <category>ASPNET</category>
      <category>dotNET</category>
      <enclosure type="image/jpeg" length="60658" url="http://crunchlife.com/files/lock.jpg"/>
      <trackback:ping>http://crunchlife.com/articles/trackback/66</trackback:ping>
    </item>
    <item>
      <title>Rockscroll Visual Studio Add-in</title>
      <description>&lt;p&gt;&lt;img src="/files/rockscroll.jpg" class="right" /&gt;Last Friday, &lt;a href="http://www.hanselman.com/blog/" target="_blank"&gt;Scott Hanselman&lt;/a&gt; announced the release of the &lt;a href="http://www.hanselman.com/blog/IntroducingRockScroll.aspx" target="_blank"&gt;Rockscroll&lt;/a&gt; Visual Studio Add-in. Rockscroll replaces Visual Studio&amp;#8217;s code-view scrollbar with a miniature visual representation of your source code. This feature makes navigation in large source files that much easier.&lt;/p&gt;

&lt;p&gt;Before Rockscroll, I&#8217;d oftentimes make mental notes of the scrollbar&#8217;s position while traversing code. That, and when spending a lot of time on a project I&#8217;d become so familiar with the source code that I&#8217;d begin to recognize most code blocks by shape. Rockscroll provides both of these &lt;a href="http://en.wikipedia.org/wiki/Mnemonic" target="_blank"&gt;mnemonic devices&lt;/a&gt;, but with less brain work. That is a good thing. Thank you, Rocky Downs. Can I have this in NetBeans? :)&lt;/p&gt;</description>
      <pubDate>Tue, 13 May 2008 06:32:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:39041988-d9be-43b4-a6e3-b5ea8de816c0</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/05/13/rockscroll-visual-studio-add-in</link>
      <category>Visual Studio</category>
      <category>dotNET</category>
    </item>
    <item>
      <title>A Few Date Methods</title>
      <description>&lt;p&gt;An ASP.NET project of mine recently required the calculation of the start and end date of the current date&amp;#8217;s previous month. This was more difficult putting into words than code.  It did, however, get me thinking about other common date routines.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public static DateTime FirstDayOfPreviousMonth
{
    get
    {
        return new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1);
    }    
}

public static DateTime LastDayOfPreviousMonth
{
    get
    {
        return new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddDays(-1);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Being preemptive, I decided to include a few methods for determining the start and end date of the current date&amp;#8217;s fiscal quarter. I started by calculating the current date&amp;#8217;s quarter. This was accomplished with just a little division.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public static int CurrentQuarter
{
    get
    {
        return (DateTime.Now.Month + 2) / 3;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finding the start and end dates of the current quarter was harder, but could still be expressed in a single line of code (or two).&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;public static DateTime FirstDayOfCurrentQuarter
{
    get
    {
        return new DateTime(DateTime.Now.Year, 1 + ((CurrentQuarter - 1) * 3), 1);
    }
}

public static DateTime LastDayOfCurrentQuarter
{
    get
    {
        int lastMonthOfCurrentQuarter = 3 + ((CurrentQuarter - 1) * 3);

        return new DateTime(DateTime.Now.Year, lastMonthOfCurrentQuarter, DateTime.DaysInMonth(DateTime.Now.Year, lastMonthOfCurrentQuarter));
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I&amp;#8217;d like to extend this collection to include other common date routines. Feel free to post your date methods as comments if you&amp;#8217;d like to share.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;*The methods I&amp;#8217;ve created for calculating the current quarter&amp;#8217;s start and end dates assume the fiscal year starts on January 1st. This may not be suitable for your needs.&lt;/strong&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 06 May 2008 11:45:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:0f4f646c-7a7d-42c8-b6b1-306d40200836</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/05/06/a-few-date-methods</link>
      <category>Code Snippets</category>
      <category>dotNET</category>
      <category>CSharp</category>
      <enclosure type="image/jpeg" length="22591" url="http://crunchlife.com/files/clock.jpg"/>
    </item>
    <item>
      <title>System.Drawing.Color Hex Values</title>
      <description>&lt;p&gt;Do you know the &lt;a href="http://en.wikipedia.org/wiki/Hexadecimal" target="_blank"&gt;hexidecimal&lt;/a&gt; value of PapayaWhip? How about BlanchedAlmond? Me either. I&amp;#8217;m not a big fan of the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.drawing.color.aspx" target="_blank"&gt;System.Drawing.Color&lt;/a&gt; structure in the Microsoft .NET Framework. I don&amp;#8217;t think the addition of color names makes good framework design sense. Unless you&amp;#8217;re an Interior Designer; the majority of &lt;a href="http://msdn2.microsoft.com/en-us/library/system.drawing.color_properties.aspx" target="_blank"&gt;these&lt;/a&gt; colors won&amp;#8217;t make sense to you either.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve recently spent time reworking a few design elements of an ASP.NET website. All design related ASP.NET attributes were replaced with &lt;a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets" target="_blank"&gt;Cascading Style Sheets (CSS)&lt;/a&gt; where applicable. Unfortunately the website was spattered with named colors from the System.Drawing.Color structure. To help replace these named colors with hexadecimal values, I found the following resource extremely helpful.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx" target="_blank"&gt;http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 16 Apr 2008 16:29:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:639ae4c8-8229-4ae4-83da-ae27bffdeb7d</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/04/16/system-drawing-color-hex-values</link>
      <category>Expect the Unexpected</category>
      <category>ASPNET</category>
      <category>dotNET</category>
      <trackback:ping>http://crunchlife.com/articles/trackback/54</trackback:ping>
    </item>
    <item>
      <title>Expect the Unexpected: Source Fource</title>
      <description>&lt;p&gt;OK, &lt;a href="http://msdn.microsoft.com/events/hero/" target="_blank"&gt;this&lt;/a&gt; is ridiculous. I must be getting too old for their marketing demographic. I do, however, look remarkably similar to figure below when wearing my &lt;a href="http://en.wikipedia.org/wiki/Dobak" target="_blank"&gt;dobak&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/fource.gif"&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 20 Feb 2008 08:09:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:70be9b5b-b48b-4c95-95ba-e0ae2cc01447</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/02/20/expect-the-unexpected-source-fource</link>
      <category>Expect the Unexpected</category>
      <category>dotNET</category>
      <enclosure type="image/gif" length="13730" url="http://crunchlife.com/files/fource.gif"/>
    </item>
    <item>
      <title>Automated Build Flurry</title>
      <description>&lt;p&gt;&lt;a href="http://www.buildsonmymachine.com/" target="_blank"&gt;&lt;img src="/files/phyllis.jpg" class="right"&gt;&lt;/a&gt;Quite a few automated build articles have been cropping up this week over at &lt;a href="http://www.codebetter.com" target="_blank"&gt;CodeBetter.Com&lt;/a&gt;. The first, &lt;a href="http://codebetter.com/blogs/kyle.baley/archive/2008/02/11/how-do-you-build-your-application.aspx" target="_blank"&gt;How do you build your application?&lt;/a&gt;, by Kyle Baley, asks Developers of the .NET community how they manage builds using the &lt;a href="http://nant.sourceforge.net/" target="_blank"&gt;NAnt&lt;/a&gt; toolkit.  Jeffrey Palermo responded with a &lt;a href="http://codebetter.com/blogs/jeffrey.palermo/archive/2008/02/11/nant-0-86-beta-1-nightly-build-seamlessly-supports-net-3-5-and-a-host-of-other-platforms.aspx" target="_blank"&gt;helpful post&lt;/a&gt; including a &lt;a href="http://palermo.googlecode.com/svn/automatedbuilddemo/trunk/AutomatedDemo.build" target="_blank"&gt;link&lt;/a&gt; to his own NAnt build template.  Kyle then followed-up with a few &lt;a href="http://codebetter.com/blogs/kyle.baley/archive/2008/02/12/you-broke-the-build.aspx" target="_blank"&gt;humorous links&lt;/a&gt; to graphics of common build scenarios. &lt;/p&gt;

&lt;p&gt;CodeBetter.Com has provided me with an overwhelming amount of great .NET content over the years and the above articles couldn&amp;#8217;t have arrived at a better time. My spare cycles at Primus Technologies Corporation have been few and far between, but those found have been spent configuring the companies &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration" target="_blank"&gt;Continous Integration&lt;/a&gt; system. I must admit that I was pleased that my own NAnt build script looked remarkably similar to Jeffrey Palermo&amp;#8217;s template. :)&lt;/p&gt;

&lt;p&gt;Of all of the work involved in developing software, build automation and Continuous Integration are my favorite. When Continuous Integration is implemented correctly it should function like an &lt;a href="http://en.wikipedia.org/wiki/Assembly_line" target="_blank"&gt;assembly line&lt;/a&gt;. Just like Ford Motor Company, your software will see improvements in efficiency and development time. If you&amp;#8217;re a .NET Developer and confused by what I&amp;#8217;ve written thus far then you should definitely familiarize yourself with these concepts. At the very least, I&amp;#8217;d recommend researching the following tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET" target="_blank"&gt;CruiseControl.NET&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://nant.sourceforge.net/" target="_blank"&gt;NAnt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/wea2sca5(VS.80).aspx" target="_blank"&gt;MSBuild&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.nunit.org/index.php" target="_blank"&gt;NUnit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://ndoc.sourceforge.net/" target="_blank"&gt;NDoc&lt;/a&gt; / &lt;a href="http://articles.techrepublic.com.com/5100-3513-6174811.html" target="_blank"&gt;Sandcastle&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb429476(vs.80).aspx" target="_blank"&gt;FxCop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, &lt;a href="http://www.hanselman.com/" target="_blank"&gt;Scott Hanselman&lt;/a&gt; has a &lt;a href="http://hanselminutes.com/archives.aspx" target="_blank"&gt;few podcasts&lt;/a&gt; that could also be helpful. Listen carefully, read diligently, and improve your software. Be better at your craft.&lt;/p&gt;</description>
      <pubDate>Tue, 12 Feb 2008 14:39:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:52c33dc4-f559-4801-a059-01cdc0b8fd12</guid>
      <author>Ryan Baxter</author>
      <link>http://crunchlife.com/articles/2008/02/12/automated-build-flurry</link>
      <category>dotNET</category>
      <category>Continuous Integration</category>
      <category>Programming</category>
      <enclosure type="image/jpeg" length="94709" url="http://crunchlife.com/files/phyllis.jpg"/>
    </item>
  </channel>
</rss>
