Welcome to Atalasoft Community Sign in | Join | Help

Debugging your custom NAnt tasks

Now that we've got some custom tasks, they might not behave as expected.  The next problem is debugging these tasks.  The biggest issue with this is if it's a problem that only is exposed on the build machine.  In our case at Atalasoft, builds are complicated to start.  I've made the build scripts generic enough that they can follow branches, and the changes are reflected through command line flags to NAnt that change the build script behavior.  As a result, starting these builds in as-close-as-possible way to the build server environment means running in the build environment, and the build environment get's kicked by cruise control.  Without some really amazing timing, attaching to that NAnt process in the debugger is hard, right?  Wrong.  Enter: System.Diagnostics.

Ok, this is nothing new to most developers, but you can make NAnt and System.Diagnostics play off each other in a way that makes your scripts and custom tasks easy to debug.

On my first iteration, I simply put a Debugger.Launch(); call in where I wanted the debugger to be attached.  This is all well and good, except that I have to rebuild the assembly and distribute it to the build server.  Having 3 build servers and our NAnt tasks in source control, this isn't such a simple process.  Instead, I wanted to make sure I could easily change the build script on specific tasks where I needed debugging, and only there.  For this, I refactored the Tasks types, and stuck in a new AtalaTask class, which is to be inherited by all my custom tasks.  AtalaTask inherits NAnt.Core.Task, and places one more boolean task attribute in (like the "verbose" attribute in Task) called "debug,” and has its own AtalaExecuteTask() to take place of the ExecuteTask().  But having this AtalaTask type means I can make global changes to all my custom tasks easily in the future:

using NAnt.Core;

using NAnt.Core.Attributes;

using System.Diagnostics;

 

namespace Atalasoft.NAnt.Tasks

{

    public abstract class AtalaTask : Task

    {

        protected bool _debugTask = false;

        [TaskAttribute("debug", Required = false)]

        [BooleanValidator()]

        public bool DebugTask {

            get { return _debugTask; }

            set { _debugTask = value; }

        }

 

        protected override void ExecuteTask()

        {

            if (DebugTask && !Debugger.IsAttached)

                Debugger.Launch();

 

            AtalaExecuteTask();

        }

 

        protected abstract void AtalaExecuteTask();

    }

}

Now, when you enter the debugger you can set a breakpoint in your AtalaExecuteTask() function and do a little jig.  To take advantage of this, just set the debug attribute on your task to true and the debugger will prompt you when it hits that point:

    <AtalaFileRegex debug="true">

 

jit1 

 

jit2

 

Now you can get smashing on that F10 key!

Published Thursday, July 10, 2008 11:20 AM by dterrell

Comments

No Comments
Anonymous comments are disabled