- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Tuesday, April 29, 2008

How to debug MSBuild tasks

A question that comes up pretty frequently is "How can I debug an MSBuild task"? It's actually pretty simple. In this post I will describe how to easily an effectively debug MSBuild tasks that you are creating. In this example I will be demonstrating a task from my open source tasks at www.codeplex.com/Sedodream. The task is one that was contributed by Grant Holliday.

First in the project where your tasks are contained create a folder that will be used to contain sample MSBuid files that can be used to debug the tasks. This is also a good idea, because it will show people how to use your tasks. If you are don't want to mix samples & code in the same project then just make sure in your build you copy the files to the correct locations. In the sample project, which you can download at the bottom, the folder is named Samples. When you add MSBuild files to the folder make sure you set the file to be copied to the output folder as well. See the image below.

By setting this, the file will be copied to the output folder when the project is built. Since it will be in the output folder we can use a relative path to get to the assembly that contains the task. Take a look at the sample MSBuild file for this task.

<?xml version="1.0" encoding="utf-8"?>

<Project ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup>

    <TaskLocation Condition="$(TaskLocation)==''">$(MSBuildProjectDirectory)\..\DebugTask.dll</TaskLocation>

  </PropertyGroup>

   <UsingTask TaskName="CreateGuid" AssemblyFile="$(TaskLocation)"/>

 

  <Target Name="Example">

    <Message Text="Starting example" />

    <CreateGuid>

        <Output PropertyName="Guid" TaskParameter="Output"/>

      </CreateGuid>

    <Message Text="Guid: $(Guid)" />

   </Target>

</Project>

 

The line highlighted contains the path to the assembly that contains the task. This path is relative to the location in the output folder, not the source folder. Also another thing to take note, is that we only write to the TaskLocation property if it is empty. This is useful because you can overwrite the location through command line parameters if necessary. But this shouldn't be needed for what we are trying to accomplish here.

After you create the sample, build the solution. And open a command prompt to verify that it works. Here is a sample of the result of this project file.

Once you've verified that that MSBuild file works then you can right click on the project that contains your task, and select properties. From there go to the debug tab. What we want to do is start the msbuild.exe executable on that sample project file. To do this fill in the full path to it in the Start External program text box, i.e. 'C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe'. In the command line arguments you should pass the name of the project file followed by any msbuild parameters. Typically I will attach a file logger to the process. Finally you should set the working directory to the folder containing the sample. The result should look something like the image shown below.

Following this set a break point in your task, set the project as the startup project and hit F5! Another thing to take note of is that these properties are stored in the .user file so it shouldn't affect any other developers on your team.

Below is the link containing a simple solution that was used here.

 

DebugTask.zip

Sayed Ibrahim Hashimi

msbuild | Visual Studio Tuesday, April 29, 2008 6:10:03 AM (GMT Daylight Time, UTC+01:00)  #     | 
Tuesday, April 15, 2008

MSBuild + JSLint = Good Javascript

Recently I was introduced to a tool that was to a tool that would analyze Javascript for syntactical errors as well as usage of bad practices. This tool is JSLint. Douglas Crockford from Yahoo! created, and maintains, JSLint. If you haven't heard of him, he is a well known Javascript expert.

Now how can we verify our Javascript with JSLint & MSBuild? In my open source project Sedodream MSBuild I have created a new JSLint task. You can get the installer by going to http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=Sedodream&ReleaseId=12530. After you install the msi you can follow these steps to invoke the JSLint on your projects.

Edit your web project file and include the following snippet before the </Project> tag.

<Import Project="$(MSBuildExtensionsPath)\Sedodream\Sedodream.tasks"/>

<Import Project="$(MSBuildExtensionsPath)\Sedodream\JSLint.targets"/>

 

<PropertyGroup>

<BuildDependsOn>

$(BuildDependsOn);

RunJSLint;

</BuildDependsOn>

</PropertyGroup>

 

The first line includes makes the tasks from my project available, and the second line includes the file that knows how to execute the JSLint tool. Following that I extend the build process to execute the RunJSLint target. If you are not familiar with this take a look at my article Inside MSBuild.

After you do this you may be prompted with a security warning from Visual Studio, you should pick 'Load Project Normally'. You can read more about how to disable it at http://msdn2.microsoft.com/en-us/library/ms228217.aspx. I chose to not have my installer set that registry flag. For the time being I think that users should make that decision themselves, although I would like to think I'm trustworthy J

After you do this and allow Visual Studio to load the project normally, if your create Javascript files that have errors, or JSLint doesn't like you will be warned in the error list as shown below.

 

With that being said keep in mind this is a V1 deal, so this may not work perfect. I am working to make sure that it works well, but it was kinda tricky to get this to work period!

As always I welcome your feedback and I will post more info about this later. Oh yeah by default from JSLint the GoodParts are enforced keep an eye on this blog, or send me a message, to see how to change that.

Sayed Ibrahim Hashimi

msbuild | Visual Studio | Javascript Tuesday, April 15, 2008 6:25:01 AM (GMT Daylight Time, UTC+01:00)  #     |