Mike's profileFreeToDevBlogLists Tools Help

FreeToDev

A technical blog by Mike Fourie, Team System MVP
June 24

MSBuild 4.0 BeforeTargets and AfterTargets

Visual Studio 2010 Beta 1 gives the wider community their first look at what is on offer in MSBuild 4.0. In this post I’ll briefly cover the new BeforeTargets and AfterTargets features.

These targets sit in the new MSBuild.Construction namespace and on initial inspection, they provide you with the ability to plug in targets to alter the execution path of a MSBuild file.

Lets cover this with a basic example. Running the following sample,

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

  <Target Name="Default">
    <Message Text="Hello from Default"/>
  </Target>

</Project>

we get the expected:

Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
  Hello from Default
Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

Now suppose you wanted to run a target before the Default target. In .NET 3.5 you would use DependsOnTargets as shown with the following:

 

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

  <Target Name="Default" DependsOnTargets="DefaultDependsOn">
    <Message Text="Hello from Default"/>
  </Target>

  <Target Name="DefaultDependsOn">
    <Message Text="Hello from DefaultDependsOn"/>
  </Target>

</Project>

which would result in:

Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
  Hello from DefaultDependsOn
Default:
  Hello from Default
Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

So what’s wrong with DependsOnTargets? Well, not a lot, however the above implementation does create an explicit bind between the targets and may reduce your ability to reuse the default target efficiently.

 

Enter BeforeTargets

In MSBuild 4.0 you can achieve the same result by using the following

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

  <Target Name="Default">
    <Message Text="Hello from Default"/>
  </Target>

  <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
    <Message Text="Hello from DefaultBeforeTarget"/>
  </Target>

</Project>

which results in:

Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
  Hello from DefaultBeforeTarget
Default:
  Hello from Default
Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

So we get the same functionality, but our targets are arguably more reusable. I don’t think there is a need to go and re-write all your code, but remember that you have this feature in your tool belt in 4.0.

Now it may be that I’ve used it a lot, but DependsOnTargets makes a lot of sense to me. It does ‘as it reads’, i.e. the Default target depends on Targets xyz… A minor concern I have with this new feature is that it doesn’t do ‘as it reads’. The first time i saw a sample with this I expected that all the BeforeTargets would run before the named target. Perhaps a better name would be RunBeforeTargets, which makes it clear that the named target will run before all the targets listed. The same logic could be applied to AfterTargets (or perhaps a better named RunAfterTargets)

 

Enter AfterTargets

In a very similar light, the new AfterTargets feature allows us to run a target after a given target. Running the following sample:

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

  <Target Name="Default">
    <Message Text="Hello from Default"/>
  </Target>

  <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
    <Message Text="Hello from DefaultBeforeTarget"/>
  </Target>

  <Target Name="DefaultAfterTarget" AfterTargets="Default">
    <Message Text="Hello from DefaultAfterTarget"/>
  </Target>
</Project>

we get:

Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
  Hello from DefaultBeforeTarget
Default:
  Hello from Default
DefaultAfterTarget:
  Hello from DefaultAfterTarget
Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

 

But DependsonTargets Rules!

So you can see how these two new features provide the ability to easily tweak execution. You can also plug into existing target frameworks without affecting other users. Now what of the DependsOnTargets in 4.0? It still lives on of course and its important to understand the order of execution.

Take the following example:

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

  <Target Name="Default" DependsOnTargets="DefaultDependsOn">
    <Message Text="Hello from Default"/>
  </Target>

  <Target Name="DefaultDependsOn">
    <Message Text="Hello from DefaultDependsOn"/>
  </Target>

  <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
    <Message Text="Hello from DefaultBeforeTarget"/>
  </Target>

  <Target Name="DefaultAfterTarget" AfterTargets="Default">
    <Message Text="Hello from DefaultAfterTarget"/>
  </Target>
</Project>

Would you expect to see DefaultBeforeTarget or DefaultDependsOn execute first? Below is the result:

Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
  Hello from DefaultDependsOn
DefaultBeforeTarget:
  Hello from DefaultBeforeTarget
Default:
  Hello from Default
DefaultAfterTarget:
  Hello from DefaultAfterTarget
Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

So as you can see, order of execution is DependsOnTargets, BeforeTargets, [NamedTarget], AfterTargets.

What do you think of this new feature? Can you think of better names or do they make sense to you?

--- Mike

Are you ready for .NET 4.0?

Check out the .NET Framework Compatibility Blog for all the latest information regarding compatibility.

You can also follow a walkthrough here

June 11

Inline coding in MSBuild 3.5

Stephen Cleary has just checked in the first version of the DynamicExecute task. This will ship in version 3.5.4.0 of the MSBuild Extension Pack, but if you compile the code yourself, you can start using it now.

We’d appreciate any feedback you have. Download

Documentation for the task is provided here

June 07

MSBuild Extension Pack 3.5.3.0 --- Available now

We’ve just shipped the latest release of the MSBuild Extension Pack! This release slipped in schedule a tiny bit but includes over 40 new tasks and represents a 20% increase in our code base.

ScreenShot004

Thanks to all those who have contributed to making this significant release. Download here

PS, you can catch the latest updates on Twitter: http://twitter.com/msbep

Mike

May 06

Planning for TFS 2010

Brian Harry has posted a few more details concerning system requirements and more here.

I’ve updated my previous diagrammatic overview to include this new information.

Download

ScreenShot015

April 08

Team System 2010 --- Start Your Engines…

Visual Studio Team system will soon be going into Beta and I look forward to getting closely acquainted with it and posting some helpful blog posts.

Brian Harry has just posted a great overview of what to expect: Team System 2010 Overview

Remember, if you are planning on adopting 2010, see this post: Planning for Team Foundation Server 2010

Mike

April 06

MSBuild Extension Pack Interview

I recently did an interview with Derek Hatchard covering the MSBuild Extension Pack. You can hear about how it started, what it is and what we have in store for future releases… listen here.

Team System MVP

image002(2) Last week I received a notification from Microsoft that I had been awarded the 2009 Microsoft® Team System MVP Award!

I’d like to thank those involved in my nomination and look forward to a successful year working more closely with the Team System family.

Mike

March 15

Available now --- MSBuild Extension Pack 3.5.2.0

The 3.5.2.0 release has now been uploaded to CodePlex. Thanks to all those who have contributed to this release over the past few months.

In terms of changes, this release is not as large as the 3.5.1.0 release, however it includes some great new additions, enhancements and fixes. For full details of all changes, please see the Version History in the Help File or online help.

Thanks for all the feedback and keep it coming, we’re now working on the 3.5.3.0 and 4.0.0.0 releases.

Mike

March 13

MSBuild Sidekick v2.3 ships

Attrice have shipped version 2.3 of their MSBuild Sidekick which now supports the MSBuild Extension Pack.

Download

Microsoft StyleCop 4.3.1.3 ships

To quote their blog:

We have just released an update to StyleCop 4.3 which contains a number of bugfixes as well as a small number of new features. In particular:

  • Ability to use <include> tags within Xml header documentation to pull docs from external files.
  • Get accessor in property required to appear before set accessor
  • .generated.cs files ignored by default

Bugfixes:

  • 18: Partial methods not handled correctly
  • 31: Documentation rules should understand <include> element
  • 56: Require get accessor before set accessor
  • 63: When documenting a generic class, only allows <see cref="MyClass"/> and not <see cref="MyClass`1"/>.
  • 70: Analysis of files in websites crashes Visual studio 2005 and 2008
  • 74: SA1623 and SA1624 warnings appears in wrong situations
  • 82: 'using' statement does not require curly brackets
  • 88: Class without explicit access modifier marked as "public" instead of "internal"
  • 90: False warning: SA1119: The line contains unnecessary parenthesis
  • 93: Ignore .generated.cs files
  • 94: Style Cop Crashes With A Blank Definition File
  • 95: SA1101 isn't raised in method calls when the return value of the method is used.
  • 98: VS crashed for webservices.
  • 121: False syntax error with a nullable generic type reference.
  • 124: LINQ operator "let" cause SA0101 when used with "condition ? true : false" syntax
  • 151: False syntax error with a defaulted array.

Please upgrade to the new version, especially if you are hit by the crash in web projects.”

Download

February 22

MSBuild Extension Pack 3.5.2.0

Hoping to get this next version shipped within the next 3 weeks, so if you are sitting on any bugs, now would be a great time to submit them to the CodePlex site…

Mike

December 01

Available now --- MSBuild Extension Pack 3.5.1.0

A little over seven weeks ago we released version 3.5.0.0 of the MSBuild Extension Pack which provided over 170 tasks. The response from the community has been very positive and today we are pleased to announce the availability of version 3.5.1.0 which provides over 230 tasks.

There have been almost one hundred changes overall and as far as we know (hope), we’ve maintained backwards compatibility, so your upgrade should be a painless experience.

Here are some of the highlights of the new release.

1. Visual Studio IntelliSense for all tasks

clip_image002

2. Online Help

clip_image004

3. Support for Attrice MSBuild Sidekick v2

clip_image006

4. 70 new tasks / features

For full details of all changes, please see the Version History in the Help File.

Thanks for all the feedback and keep it coming, we’re already hard at work on the next release...

November 27

A new Home Page for the MSBuild Extension Pack

A new homepage for www.msbuildextensionpack.com just went live. It’s fairly basic at the moment but we have some great things to come. The first new feature is online help. The help that is currently hosted is for version 3.5.1.0 which is in beta and due to ship on 1 Dec 2008.

If you haven’t tried the beta yet, please give it a go and let us know how you get on. Please also feel free to comment on our online help. We will continue to ship a standalone chm file with each release.

November 24

MSBuild Extension Pack 3.5.1.0 Beta Released

We expect to be in beta for 1 week (pending feedback) and to ship the 'stable' 3.5.1.0 release on 1 Dec 2008.

What's New: Please consult the Version History page in the Help File for full details

image

Download

November 21

Team Foundation Server Build 2008 Reference DeskSheet – V2.0

A few minor updates. A handy reference to aid your work with building software in TFS 2008

ScreenShot023

November 17

Team Foundation Server Build 2008 Reference DeskSheet

UPDATE: V2 is available now.

A handy reference to aid your work with building software in TFS 2008

image

Download

November 13

Comments Blocked

I’ve decided to disable comments on blog posts due to the high level of spam. If you need to contact me, use the ‘Send a Message’ link on this site. I believe that the new ‘Wave 3’ refresh of spaces will offer better spam controls, so I’ll re-enable comments when it is released.

November 10

Breaking Changes in Visual C# 2008 Service Pack 1

I was made aware of an interesting site today that lists the breaking changes made to C# in VS2008 SP1. Usually people have problems with service pack installers rather than breaking changes, however it may be worth taking a read if you plan on upgrading.

You can view the changes here.

November 09

User Interaction in MSBuild

Although most MSBuild applications will happily run with no user interaction, sometimes it may be useful to prompt a user with a confirmation or request a value for use in further, possibly conditional, processing.

In the following simple examples I’ll use a few tasks from the MSBuild Extension Pack to illustrate various options for interacting with the user.

Note that many of the tasks used here provide additional properties for customising their usage. Please consult the latest help file for full details.

Alert and Delay

Although it requires no physical interaction from the user, a simple combination of playing a sound, displaying a message and then giving the user a chance to read the message can provide a simple but valuable user experience.

Sample:

<!-- Play an audible alert -->

<MSBuild.ExtensionPack.UI.Console TaskAction="Beep" Repeat="10" Duration="5000" Frequency="1000"/>

<!-- or play a custom sound -->

<!-- <MSBuild.ExtensionPack.Multimedia.Sound TaskAction="Play" SoundFile="C:\Windows\Media\notify.wav" Repeat="10"/>-->

<!-- Display a message -->

<Message Text="Please take note of this important announcement" Importance="High"/>

<!-- Give the user time to read the message -->

<MSBuild.ExtensionPack.Framework.Thread TaskAction="Sleep" Timeout="5000"/>

 

Console Interaction

The Console class provides the ability to read a line of input from the user. This can also be used to pause the processing of the file until the user presses an [Enter] key.

Sample:

<!-- Play an audible alert -->

<MSBuild.ExtensionPack.UI.Console TaskAction="Beep"/>

<!-- Ask the user to press enter when ready to continue -->

<MSBuild.ExtensionPack.UI.Console TaskAction="ReadLine" UserPrompt="Press [Enter] to continue..."/>

<!-- Read input from the user -->

<MSBuild.ExtensionPack.UI.Console TaskAction="ReadLine" UserPrompt="Please enter your Name and press [Enter]" ToUpper="true">

<Output TaskParameter="UserResponse" PropertyName="Line"/>

</MSBuild.ExtensionPack.UI.Console>

<Message Text="The user name is: $(Line)"/>

Output:

C:\msbuild UserInteraction.proj

Microsoft (R) Build Engine Version 3.5.30729.1

Build started 09/11/2008 17:01:09.

Project "C:\UserInteraction.proj" on node 0 (default targets).

  Press [Enter] to continue...

  Please enter your Name and press [Enter]

mike

  The user name is: MIKE

Done Building Project "C:\UserInteraction.proj" (default targets).

Build succeeded.

 

WinForm Interaction

With so much console use in MSBuild, it can be a welcome break to switch to a Windows Form to interact with the user. The Dialog task provides a way for displaying prompts and gathering normal and sensitive input.

Sample:

<!-- A simple message -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Show" Text="Hello. Press OK to continue..."/>

<!-- Give the user the option to cancel processing-->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Show" Text="Click cancel if you've had enough..." Button1Text="Continue" Button2Text="Cancel" Title="You Decide!">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Error Condition="$(Clicked) == 'Cancel'"/>

<Message Text="User Clicked: $(Clicked)"/>

<!-- A simple prompt for input -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Prompt" Title="Information Required" Button2Text="Cancel" Text="Please enter your Name below">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

<Output TaskParameter="UserText" PropertyName="Typed"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Message Text="User Clicked: $(Clicked)"/>

<Message Text="User Typed: $(Typed)"/>

<!-- A prompt for password input -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Prompt" Title="Sensitive Information Required" Button2Text="Cancel" Text="Please enter your Password below" MessageColour="Red" MaskText="true">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

<Output TaskParameter="UserText" PropertyName="Typed"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Message Text="User Clicked: $(Clicked)"/>

<Message Text="User Typed: $(Typed)"/>

<OnError ExecuteTargets="ErrorTarget"/>

Output:

clip_image002

clip_image004

Assuming I click Cancel, then all processing would stop:

 

C:\msbuild UserInteraction.proj

Microsoft (R) Build Engine Version 3.5.30729.1

Build started 09/11/2008 17:01:09.

Project "C:\UserInteraction.proj" on node 0 (default targets).

  The user has terminated processing.

Done Building Project "C:\UserInteraction.proj" (default targets). -- FAILED

Build FAILED.

If I clicked continue, we would see

clip_image006

clip_image008 

 

Full Sample

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

<PropertyGroup>

<TPath>$(MSBuildProjectDirectory)\..\MSBuild.ExtensionPack.tasks</TPath>

<TPath Condition="Exists('$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks')">$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks</TPath>

</PropertyGroup>

<Import Project="$(TPath)"/>

<Target Name="Default">

<!-- Play an audible alert -->

<MSBuild.ExtensionPack.UI.Console TaskAction="Beep" Repeat="10" Duration="5000" Frequency="1000"/>

<!-- or play a custom sound -->

<!-- <MSBuild.ExtensionPack.Multimedia.Sound TaskAction="Play" SoundFile="C:\Windows\Media\notify.wav" Repeat="10"/>-->

<!-- Display a message -->

<Message Text="Please take note of this important announcement" Importance="High"/>

<!-- Give the user time to read the message -->

<MSBuild.ExtensionPack.Framework.Thread TaskAction="Sleep" Timeout="5000"/>

<!-- Play an audible alert -->

<MSBuild.ExtensionPack.UI.Console TaskAction="Beep"/>

<!-- Ask the user to press enter when ready to continue -->

<MSBuild.ExtensionPack.UI.Console TaskAction="ReadLine" UserPrompt="Press [Enter] to continue..."/>

<!-- Read input from the user -->

<MSBuild.ExtensionPack.UI.Console TaskAction="ReadLine" UserPrompt="Please enter your Name and press [Enter]" ToUpper="true">

<Output TaskParameter="UserResponse" PropertyName="Line"/>

</MSBuild.ExtensionPack.UI.Console>

<Message Text="The user name is: $(Line)"/>

<!-- A simple message -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Show" Text="Hello. Press OK to continue..."/>

<!-- Give the user the option to cancel processing-->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Show" Text="Click cancel if you've had enough..." Button1Text="Continue" Button2Text="Cancel" Title="You Decide!">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Error Condition="$(Clicked) == 'Cancel'"/>

<Message Text="User Clicked: $(Clicked)"/>

<!-- A simple prompt for input -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Prompt" Title="Information Required" Button2Text="Cancel" Text="Please enter your Name below">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

<Output TaskParameter="UserText" PropertyName="Typed"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Message Text="User Clicked: $(Clicked)"/>

<Message Text="User Typed: $(Typed)"/>

<!-- A prompt for password input -->

<MSBuild.ExtensionPack.UI.Dialog TaskAction="Prompt" Title="Sensitive Information Required" Button2Text="Cancel" Text="Please enter your Password below" MessageColour="Red" MaskText="true">

<Output TaskParameter="ButtonClickedText" PropertyName="Clicked"/>

<Output TaskParameter="UserText" PropertyName="Typed"/>

</MSBuild.ExtensionPack.UI.Dialog>

<Message Text="User Clicked: $(Clicked)"/>

<Message Text="User Typed: $(Typed)"/>

<OnError ExecuteTargets="ErrorTarget"/>

</Target>

<Target Name="ErrorTarget">

<Message Text="The user has terminated processing."/>

</Target>

</Project>

November 08

TFS Power Tools October 2008

These have just been released… Available here

November 01

Progress on release 3.5.1.0

Progress on the next release, release 3.5.1.0, of the MSBuild Extension Pack is going well.

Please continue to provide feedback to us via the Discussions and Issue Tracker pages, or email us directly at feedback@msbuildextensionpack.com

We aim to ship 3.5.1.0 in the last week of November / first week of December 2008.

October 22

Providing IntelliSense for the MSBuild Extension Tasks

The next release of the MSBuild Extension Pack will offer IntelliSense for all tasks. It’s a small but helpful addition which makes using the tasks that little bit easier.

image

We will also ship an IntelliSense schema file for the Team Foundation Build Tasks.

image

In generating this schema file, a few undocumented properties were discovered that you may find useful:

 

    • Get: TeamFoundationServerUrl, Overwrite
    • Label: TeamFoundationServerUrl, Scope
    • SetBuildProperties: LogLocation, SourceGetVersion

Required parameters have ‘REQUIRED.’ as a prefix in the tooltips shown.

Unfortunately a bug exists in Visual Studio 2008 & SP1 which means that you will partially lose IntelliSense in the IDE if you use schema documented tasks after undocumented tasks. Here is a quick repro:

This repro uses the following simple sample

  1. <Project DefaultTargets="IntelliPain" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  2.          
  3.     <Target Name="IntelliPain">
  4.         <UnDocumentedTask AProperty="a"/>
  5.     </Target>
  6. </Project>

Step 1

  • Start typing at Line 4.
  • IntelliSense on the available tasks is seen.

clip_image002[4]

  • Continue typing at Line 4.
  • IntelliSense on the available tasks parameters is seen.
  • CTRL-SPACE can be used to display the parameter IntelliSense if it is not shown.

clip_image004[4]

Step 2

  • Start typing at Line 6 (i.e. BELOW the task which has no associated schema).
  • IntelliSense on the available tasks is seen.

clip_image006[4]

  • Continue typing at Line 6
  • IntelliSense on the available tasks parameters is NOT seen.
  • CTRL-SPACE can NOT be used to display the parameter IntelliSense.

clip_image008[4]

This bug has been reported to Microsoft but I don’t know when we can expect a fix. A workaround is to create documentation schema files for all the tasks you write (and use if they don’t already have them). There is some guidance for doing this here, and you will find more guidance in the next version of the MSBuild Extension Pack help file.

If you would like to try out these schema files now, you can download pre-release versions from the CodePlex site.

 

.

Mike Fourie

Occupation