<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>MSBuild Team Blog : How To</title><link>http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx</link><description>Tags: How To</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>7 Steps to MSBuild</title><link>http://blogs.msdn.com/msbuild/archive/2006/12/05/7-steps-to-msbuild.aspx</link><pubDate>Tue, 05 Dec 2006 04:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1208576</guid><dc:creator>msbuild</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/1208576.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=1208576</wfw:commentRss><description>&lt;P&gt;Brennan has a great &lt;A class="" href="http://brennan.offwhite.net/blog/2006/11/30/7-steps-to-msbuild/" mce_href="http://brennan.offwhite.net/blog/2006/11/30/7-steps-to-msbuild/"&gt;post&lt;/A&gt; about all things MSBuild, and covers good breadth on both&amp;nbsp;concepts, as well as the many things you may want to drive with MSBuild&amp;nbsp;(unit testing, web deployment projects,&amp;nbsp;etc). Check it out!&lt;/P&gt;
&lt;P&gt;[ Author : Faisal Mohamood ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1208576" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Faisal+Mohamood/default.aspx">Faisal Mohamood</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>/p property values are immutable - (sort of)....</title><link>http://blogs.msdn.com/msbuild/archive/2006/10/05/_2F00_p-property-values-are-immutable-_2D00_-_2800_sort-of_29002E002E002E002E00_.aspx</link><pubDate>Thu, 05 Oct 2006 18:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:794206</guid><dc:creator>msbuild</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/794206.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=794206</wfw:commentRss><description>&lt;P&gt;Hello there - sorry for the long absence, but we're back and hopefully I'll keep this going again.&lt;/P&gt;
&lt;P&gt;So there was a recent forum post about how property values that are specified from the command line are immutable - i.e. it is not straightforward to change them from within the project file. Well, this is mostly true, but there are exceptions.&lt;/P&gt;
&lt;P&gt;Let's take an example:&lt;/P&gt;
&lt;P&gt;If I've got a property in my project file defined like this,&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Configuration&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Debug&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Configuration&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;/SPAN&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/SPAN&gt;then, calling msbuild with /p:Configuration=Release will override this value (or alternatively set the value if it is not defined) for all projects that are being built. Properties that we pass in with a /p switch on the command line are known as "Global Properties" and so it will flow down to all projects that are being built - so if you were building a solution file, all projects will get the overridden value of this property. 
&lt;P&gt;Now, let's say that you have this defined in your project file:&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;AppPath&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt; '$(AppPath)' == '' &lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;bin\debug\&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;AppPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;AppPath&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt; !HasTrailingSlash('$(AppPath)') &lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;$(AppPath)\&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;AppPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What I am doing here is that I am defining a default value for AppPath property if AppPath is not defined. Additionally, I want to set it up so that if someone has specified an AppPath property, then if it does not already have a trailing slash, I'd like to add it. Looks reasonable, correct?&lt;/P&gt;
&lt;P&gt;Actually this will not work as you expect - and is something to watch out for. What happens when you specify something with a &lt;STRONG&gt;/p:AppPath=blah\&lt;/STRONG&gt; is that all in-project property definitions for AppPath are ignored&amp;nbsp;(or essentially overridden), and so none of the in-project property definitions take effect - even the ones with the condition. This makes sense if you think about it because otherwise what exactly are we supposed to override? Would that be the first definition of the property? Or should we override only those values of the property that are checking against an empty value? There isn't a clear answer. We override all property definitions and what is passed in is the effective value.&lt;/P&gt;
&lt;P&gt;Fortunately, there is a way around this if it causes you grief - but it isn't declarative like PropertyGroup. You have to use the CreateProperty task inside a target where you intend to process the property, like so:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;CreateProperty&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Value&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;$(AppPath)\&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; !HasTrailingSlash('$(AppPath)') &lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Output&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;TaskParameter&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;Value&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;PropertyName&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;AppPath&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; /&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;CreateProperty&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Alternatively (and perhaps as a&amp;nbsp;better approach), you can use a property name like AppPath as the public property you expect to override from th command line, but filter it out into a different property inside your targets that you then use for doing the actual work - like this:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;$(AppPath)&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt; '$(_validatedAppPath)' == '' &lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;bin\debug\&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt; !HasTrailingSlash('$(_validatedAppPath)') &lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;$(_validatedAppPath)\&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;_validatedAppPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;In this case, you validate the /p value and store it in an internal property that is validated, and never directly overridden from the command line.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Hope this helps, and clears some confusion on "strange behavior" if you ever encountered it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;[ Author: Faisal Mohamood ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=794206" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Faisal+Mohamood/default.aspx">Faisal Mohamood</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/Known+Issues/default.aspx">Known Issues</category></item><item><title>How To: Remove the Up-To-Date Check From the AssemblyInfoTask</title><link>http://blogs.msdn.com/msbuild/archive/2006/03/28/how-to-remove-the-up-to-date-check-from-the-assemblyinfotask.aspx</link><pubDate>Tue, 28 Mar 2006 23:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:563461</guid><dc:creator>msbuild</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/563461.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=563461</wfw:commentRss><description>&lt;P&gt;Every couple of weeks I get mail from someone who is using the AssemblyInfoTask on a build machine under source control. The question typically goes like this:&lt;/P&gt;
&lt;P&gt;I added the .targets file to my project, and it works fine on my dev machine, but doesn't do anything when I'm running it in the build lab. What's wrong? Help!&lt;/P&gt;
&lt;P&gt;The reason it "doesn't do anything" is because the default Microsoft.VersionNumber.Targets file includes MSBuild attributes that instruct the build engine to check timestamps on input and output files. These were added because it doesn't make much sense to increment the version number on an assembly if nothing is gettting re-built. This can happen if MSBuild does an incremental build on the project.&lt;/P&gt;
&lt;P&gt;In the build lab, however, all of the input files (.cs files, generally) and the output file (assemblyinfo.cs) wind up with the same timestamps when they are synchronized from the soruce code control server.&lt;/P&gt;
&lt;P&gt;To resolve this, simply remove the Inputs and Outputs attributes from the &amp;lt;Target&amp;gt; tag in the Microsoft.VersionNumber.Targets file. It should wind up looking like this:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;UpdateAssemblyInfoFiles&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=563461" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/AssemblyVersionInfo/default.aspx">AssemblyVersionInfo</category></item><item><title>How To: Bypass Post-Build Steps in a Build Lab Environment</title><link>http://blogs.msdn.com/msbuild/archive/2006/03/10/546590.aspx</link><pubDate>Sat, 11 Mar 2006 02:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:546590</guid><dc:creator>msbuild</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/546590.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=546590</wfw:commentRss><description>&lt;P&gt;(Can you tell I'm going through my folder of interesting MSBuild questions today?)&lt;/P&gt;
&lt;P&gt;Here's another good question that came across our internal discussion alias last week:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;FONT color=#0000ff&gt;Is there a quick and easy way to bypass the PostBuild steps in a project file that was created with VS.NET 2005?&amp;nbsp;I am trying to set up a master build project that will be compiling a large number of other projects, some that contain PostBuild steps that are not appropriate for our master build.&amp;nbsp;Is there something I can define that will then cause the PostBuild steps to be skipped?&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;I actually didn't know the answer to this one off the top of my head, but since the entire build process is available for the world to see, it didn't take much to figure it out. I cracked open the Microsoft.Common.Targets file in Visual Studio and looked at how the PostBuildStep is set up. Here's an excerpt from the file:&lt;/P&gt;
&lt;P&gt;&amp;lt;Target Name="PostBuildEvent" Condition="'$(PostBuildEvent)'!='' and [...]&amp;gt;&lt;/P&gt;
&lt;P&gt;Notice how the condition is set up. In the build lab, you can simply pass /p:PostBuildEvent="" on the command line to disable all the post build events in the included projects.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=546590" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Distribute Your Custom Task and .Targets file</title><link>http://blogs.msdn.com/msbuild/archive/2006/03/09/546627.aspx</link><pubDate>Thu, 09 Mar 2006 22:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:546627</guid><dc:creator>msbuild</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/546627.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=546627</wfw:commentRss><description>&lt;P&gt;We've had variations of the same question on how to distribute tasks come through both internal and external channels in the last couple of weeks. Here's one example:&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;If we have a product that is installing custom MSBuild tasks, are there any type of guidelines on where they should be installed, do they need to be registered, etc.?&lt;/FONT&gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The good news is you don't have to register anything at all. You just need to figure out what the best directory is to install your goo. Typically there's two pieces of goo that need to be installed: the assembly with the task(s) in it, and the .targets file that includes a &amp;lt;UsingTask&amp;gt;, assorted properties, and perhaps even a target override.&lt;/P&gt;
&lt;P&gt;It turns out that you'll probably want your installer to offer the user the choice of two installation points: one for installing your new MSBuild magic on a developer's machine, and another for installing it in some sort of build-lab environment. Here's a little table with the suggested installation locations:&lt;/P&gt;
&lt;P&gt;
&lt;TABLE&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH&gt;&lt;/TH&gt;
&lt;TH&gt;Developer Machine &lt;/TH&gt;
&lt;TH&gt;Build Lab &lt;/TH&gt;&lt;/TR&gt;&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;Assembly &lt;/TD&gt;
&lt;TD&gt;Global Assembly Cache &lt;/TD&gt;
&lt;TD&gt;Location of user's choosing &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;.Targets File &lt;/TD&gt;
&lt;TD&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms164309.aspx"&gt;$(MSBuildExtensionsPath)&lt;/A&gt; &lt;/TD&gt;
&lt;TD&gt;Location of user's choosing &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;This requires your setup to actually have two different .targets files, since the &amp;lt;UsingTask&amp;gt; will be different depending on where the task assembly is installed.&lt;/P&gt;
&lt;P&gt;To see all this in action I suggest downloading the &lt;A href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=93d23e13-c653-4815-9e79-16107919f93e"&gt;AssemblyInfoTask sources&lt;/A&gt;. It includes a setup project that gives the user of installing the assembly into either the GAC or to their local application data folder. This could be extended to allow installation to GAC or a folder of the user's choosing.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=546627" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Exclude Multiple Files From a Wildcard</title><link>http://blogs.msdn.com/msbuild/archive/2006/03/08/546583.aspx</link><pubDate>Thu, 09 Mar 2006 01:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:546583</guid><dc:creator>msbuild</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/546583.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=546583</wfw:commentRss><description>&lt;P&gt;We got the following question on our internal conversion discussion alias today:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;FONT color=#0000ff&gt;Is there a way to exclude two or more items from an ItemGroup using the “exclude” attribute without using a wildcard?&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;It turns out the way to do this wasn't clear from our existing &lt;A href="http://msdn2.microsoft.com/en-us/library/ms164283(VS.80).aspx"&gt;MSDN Documentation&lt;/A&gt;. Brett, our documentation writer, has a fix in the queue for the next MSDN refresh, but in the mean time here is the answer from Dan:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: Verdana"&gt;&amp;lt;ItemGroup&amp;gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: Verdana"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Compile Include="*.cs" Exclude="a.cs;b.cs"/&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: Verdana"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=546583" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Add Custom Process at Specific Points During Build (Method #2)</title><link>http://blogs.msdn.com/msbuild/archive/2006/02/10/528822.aspx</link><pubDate>Fri, 10 Feb 2006 22:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:528822</guid><dc:creator>msbuild</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/528822.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=528822</wfw:commentRss><description>&lt;p&gt;&lt;a HREF="/msbuild/archive/2005/11/23/496396.aspx"&gt;Back in November&lt;/a&gt; I wrote about a quick-and-dirty way to add custom build process into the standard Visual Studio build by overriding pre-defined targets that exist in Microsoft.Common.Targets. While this method works fine for internal build processes it can be brittle if you’re trying to deploy your build process to other teams or customers. In particular, if someone else decides to go and override the same target after you’ve done so, your customization will disappear. To handle this situation we’ve provided a second way of inserting your custom build process into the Visual Studio build: overriding properties that are used in TargetDependsOn attributes. The easiest way to understand how to do this is to look at a short snippet from Microsoft.Common.Targets: &lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Target &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Name&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;span style="COLOR: blue"&gt;Build&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;DependsOnTargets&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;$(BuildDependsOn)&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt;&lt;/span&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Notice how the Build target has a DependsOnTargets that points to the BuildDependsOn property. That means before the Build target can run, all the targets listed in BuildDependsOn have to run first:&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;BuildDependsOn&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;BeforeBuild;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;CoreBuild;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;AfterBuild&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;BuildDependsOn&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;If you want to add something to the build process that runs after everything else in the build, you’d simply create your own target and then add it to BuildDependsOn like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;BuildDependsOn&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;$(BuildDependsOn);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;MyCustomTarget&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;BuildDependsOn&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PropertyGroup&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Target&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Name&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;span style="COLOR: blue"&gt;MyCustomTarget&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Message&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Text&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;span style="COLOR: blue"&gt;Hello from MyCustomTarget&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Target&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;Notice how we’ve included the original value of BuildDependsOn in our new definition of the property. Using this pattern means that anyone who overrides the existing meaning of BuildDependsOn will include all the existing content of the property, without overwriting customizations others have made. You can use a similar approach to get your custom target to run before everything in BuildDependsOn.&lt;/p&gt;
&lt;p&gt;Here’s a list of the most commonly used *DependsOn properties:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BuildDependsOn&lt;/td&gt;
&lt;td&gt;This is the property to use if you want to insert custom process before or after the entire build process. As you might guess, this is frequently used.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CleanDependsOn&lt;/td&gt;
&lt;td&gt;This is the property to override if you want to clean up output from your custom build process.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CompileDependsOn&lt;/td&gt;
&lt;td&gt;This is a very useful property as it provides a place to insert custom process before or after the compliation step. This is frequently overriden.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In addition to the three common properties there are many other properties that are almost never used. For completeness, here’s what they are and why you might use them:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CompileLicxFilesDependsOn&lt;/td&gt;
&lt;td&gt;Targets in this property run before .licx files get compiled. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoreBuildDependsOn&lt;/td&gt;
&lt;td&gt;This is the heavy-duty part of the build process and pretty much drives the whole build.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoreCleanDependsOn&lt;/td&gt;
&lt;td&gt;This is really provided for design pattern completeness. There’s no real reason to use this instead of CleanDependsOn.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoreCompileDependsOn&lt;/td&gt;
&lt;td&gt;Interestingly this is one of only two *DependsOn properties that are defined in the language-specific targets files instead of Microsoft.Common.Targets. This is rarely used; instead, override CompileDependsOn.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CreateManifestResourceNamesDependsOn&lt;/td&gt;
&lt;td&gt;Run before the manifest resource name is created from .resx files. Rarely overridden.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CreateSatelliteAssembliesDependsOn&lt;/td&gt;
&lt;td&gt;Primarily used as a way to force intermediate satellite assemblies to be computed before the final satellite assemblies are regenerated.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GetRedistListsDependsOn&lt;/td&gt;
&lt;td&gt;While this is in the Common.Targets file and can technically be used to insert custom process around the collection of redistributable assemblies, this is really there to ensure framework path resolution happens before the lists are gathered. I doubt anyone will ever need to override this. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostBuildEventDependsOn&lt;/td&gt;
&lt;td&gt;This runs before the PostBuildEvent target is executed. This is rarely overridden since PostBuildEvent largely exists to support the legacy build extension methods offered in Visual Studio 2003 and earlier. Instead of overriding this you should consider using BuildDependsOn.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PreBuildEventDependsOn&lt;/td&gt;
&lt;td&gt;This runs before the PreBuildEvent target is executed. This is rarely overridden since PreBuildEvent largely exists to support the legacy build extension methods offered in Visual Studio 2003 and earlier. Instead of overriding this you should consider using BuildDependsOn. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrepareForBuildDependsOn&lt;/td&gt;
&lt;td&gt;This takes care of getting all the build pre-requisites done before the actual build process starts. You can think of targets in this property as being almost like initialization routines for the whole build.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrepareForRunDependsOn&lt;/td&gt;
&lt;td&gt;This is a good place to insert build process that needs to get content into place before the application is executed from within Visual Studio. Having said that, it’s rarely overridden.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrepareResourceNamesDependsOn&lt;/td&gt;
&lt;td&gt;Prepares the names of the resource files before they get passed to the complication step of the build. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrepareResourcesDependsOn&lt;/td&gt;
&lt;td&gt;Prepares the resources before they get passed to the compliation step of the build.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PublishBuildDependsOn&lt;/td&gt;
&lt;td&gt;The list of targets that must run before the project is published. Rarely, if ever, used. Instead, use PublishOnlyDependsOn.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PublishDependsOn&lt;/td&gt;
&lt;td&gt;Runs before the project is published using ClickOnce deployment outside of the IDE. It causes a build to happen before publish takes place. If you need to do work before the project is published you should override PublishOnlyDependsOn instead, since PublishDependsOn includes a call to PublishOnlyDependsOn.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PublishOnlyDependsOn&lt;/td&gt;
&lt;td&gt;Run after the IDE has completed a build and then needs to do a publish (as opposed to a command-line build where build followed by publish might happen all in one build command). If you need to do work before or after the project is published this is the property to use.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RebuildDependsOn&lt;/td&gt;
&lt;td&gt;This drives the rebuild target, and handles clean and then re-building the project. If you want to do something before or after rebuild this is the property to override.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ResGenDependsOn&lt;/td&gt;
&lt;td&gt;This is used to drive the resource generation step of the build process. If you need to do something before or after resource generation, this is the property to override. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ResolveAssemblyReferencesDependsOn&lt;/td&gt;
&lt;td&gt;This has a similar story to GetRedistListsDependsOn. It’s unlikely anyone will ever need to override this.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ResolveReferencesDependsOn&lt;/td&gt;
&lt;td&gt;This is the workhorse for resolving assembly references, one of the most complicated parts of the build process. If you want to do special work to handle assembly resolution, or do work immediately following the resolution of all the assembly references, this is the property to use. Having said that, it’s rarely overridden.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RunDependsOn&lt;/td&gt;
&lt;td&gt;Targets in this property will get executed before the compiled application is run. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnmanagedRegistrationDependsOn&lt;/td&gt;
&lt;td&gt;Targets in this property are run before the main assembly is registered for COM interop.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnmanagedUnregistrationDependsOn&lt;/td&gt;
&lt;td&gt;This runs before the main assembly is registered for COM interop purposes.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BuiltProjectOutputGroupDependsOn&lt;br /&gt;DebugSymbolsProjectOutputGroupDependsOn&lt;br /&gt;DocumentationProjectOutputGroupDependsOn&lt;br /&gt;SatelliteDllsProjectOutputGroupDependsOn&lt;br /&gt;SourceFilesProjectOutputGroupDependsOn&lt;br /&gt;ContentFilesProjectOutputGroupDependsOn &lt;/td&gt;
&lt;td&gt;Targets in these properties are run before &lt;a HREF="/msbuild/archive/2005/11/17/493504.aspx"&gt;output groups&lt;/a&gt; are computed for the IDE.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;[ Author: Neil Enns ]&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=528822" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Use the AssemblyInfoTask With ASP.NET Web Deployment Projects</title><link>http://blogs.msdn.com/msbuild/archive/2006/01/26/how-to-use-the-assemblyinfotask-with-asp-net-web-deployment-projects.aspx</link><pubDate>Thu, 26 Jan 2006 22:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:517531</guid><dc:creator>msbuild</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/517531.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=517531</wfw:commentRss><description>&lt;P&gt;About once a week we get a question from someone who wants to know how to set the assembly version information on ASP.NET projects. I spoke with Bradley, a development lead over in the ASP.NET team who worked on the &lt;A href="http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx"&gt;Web Deployment Projects&lt;/A&gt;, and it turns there are two ways you can do this.&lt;/P&gt;
&lt;P&gt;If the only thing you're interested in doing is setting the version number on the web deployment project you can do that directly through UI properties on the deployment project instead of editing MSBuild files and downloading another task. For more information look at their &lt;A href="http://download.microsoft.com/download/1/5/4/1541980a-d8fc-407b-8c9f-c2df5445b041/Using%20web_deployment_projects_final.doc"&gt;walkthrough documentation&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;If you want to set the version number as part of a larger build process that includes desktop assemblies and other class libraries you can use the &lt;A href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=93d23e13-c653-4815-9e79-16107919f93e"&gt;AssemblyInfoTask&lt;/A&gt; and custom MSBuild XML. To make this work you need to add an assemblyinfo.cs (or .vb) to a folder called &lt;A href="http://dotnetjunkies.com/QuickStartv20/aspnet/doc/pages/code.aspx"&gt;app_code&lt;/A&gt; under your top level directory. Once that file is there you can use the AssemblyInfoTask as you normally would to set the version number, and then use the Web Deployment Project to do the compliation of the assembly for the web.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=517531" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/AssemblyVersionInfo/default.aspx">AssemblyVersionInfo</category></item><item><title>How To: Obtain Initial Property Values in a Logger</title><link>http://blogs.msdn.com/msbuild/archive/2006/01/25/517484.aspx</link><pubDate>Wed, 25 Jan 2006 20:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:517484</guid><dc:creator>msbuild</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/517484.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=517484</wfw:commentRss><description>&lt;P&gt;We got a question on our &lt;A href="mailto:msbuild@microsoft.com"&gt;MSBuild Feedback&lt;/A&gt; alias today that went something like this:&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;How do I obtain all the initial property values in the project file in my custom logger?&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It's not immediately obvious from our object model, but you can do this. In the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms124426(en-US,VS.80).aspx"&gt;ProjectStarted event&lt;/A&gt; the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms124414(en-US,VS.80).aspx"&gt;ProjectStartedEventArgs&lt;/A&gt; contains a &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.projectstartedeventargs.properties.aspx"&gt;Properties&lt;/A&gt; member. You can iterate over this with a foreach to look at all the values of the properties in the project file.&lt;/P&gt;
&lt;P&gt;Thanks to Dan for the question, and to Jay for the answer.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=517484" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Implementing Custom Tasks - Part I</title><link>http://blogs.msdn.com/msbuild/archive/2006/01/21/515834.aspx</link><pubDate>Sun, 22 Jan 2006 02:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:515834</guid><dc:creator>msbuild</dc:creator><slash:comments>51</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/515834.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=515834</wfw:commentRss><description>&lt;P&gt;While MSBuild is all about build customization,we never really blogged about what is involved in implementing custom tasks.&amp;nbsp; Partly, I suppose that's because implementing a custom task is as easy as falling off a log most of the time: 1) Subclass &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.utilities.task.aspx"&gt;Microsoft.Build.Utilities.Task&lt;/A&gt; abstract class 2) Implement the &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.utilities.task.execute.aspx"&gt;Execute&lt;/A&gt; method&lt;/P&gt;
&lt;P&gt;But there's a lot more to tasks than just that. In this series of posts, I hope to cover all there is to know about MSBuild tasks - both at a conceptual level as well as on variations such as &lt;A href="http://msdn2.microsoft.com/en-us/library/ms126394(en-us,VS.80).aspx"&gt;ToolTask&lt;/A&gt;, &lt;A href="http://msdn2.microsoft.com/en-us/library/ms126182(en-us,VS.80).aspx"&gt;AppDomainIsolatedTask&lt;/A&gt;, etc.&amp;nbsp; In this post I'd like to set the context for discussing some of those topics.&lt;/P&gt;
&lt;P&gt;A task, in principle is nothing more than an implementation of the GoF &lt;A href="http://c2.com/cgi/wiki?CommandObject"&gt;Command&lt;/A&gt; Object Pattern i.e.&amp;nbsp;an object that knows how to perform an action encapsulated via an Execute method. While it is possible to utilize tasks programmatically via code, the primary motivation was to provide a way of performing self standing units of work within build targets.&lt;/P&gt;
&lt;P&gt;In the crudest form, a task is a type that implements the &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.itask.aspx"&gt;Microsoft.Build.Framework.ITask&lt;/A&gt; interface from the Microsoft.Build.Framework assembly.&amp;nbsp; Here's a simple implementation of a task that can set environment variables.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;using Microsoft.Build.Framework;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;namespace SimpleTask&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class SetEnvironmentVariable : ITask&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private IBuildEngine engine;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBuildEngine BuildEngine&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return engine; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { engine = value; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private ITaskHost host;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ITaskHost HostObject&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return host; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { host = value; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string name;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Required]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return name; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { name = value; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string varValue;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Required]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Value&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return varValue; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { varValue = value; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool Execute()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Environment.SetEnvironmentVariable(name, varValue);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string message = string.Format("Environment Variable {0} set to {1}", name, varValue);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BuildMessageEventArgs args = new BuildMessageEventArgs(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; message, string.Empty, "SetEnvironmentVariable", MessageImportance.Normal);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; engine.LogMessageEvent(args);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In addition to the Execute method that performs the actual work, at the minimum all tasks must expose two properties - BuildEngine of type &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.ibuildengine.aspx"&gt;IBuildEngine&lt;/A&gt;, and HostObject of type &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.itaskhost.aspx"&gt;ITaskHost&lt;/A&gt;. For the purposes of most tasks, the implementation I have shown here will suffice. &lt;/P&gt;
&lt;P&gt;IBuildEngine itself is used by the task to report messages, warnings and errors to the MSBuild engine.&amp;nbsp; ITaskHost is an interface that is used to represent host objects that can form a basis for richer communication between tasks and an environment that hosts MSBuild (such as Visual Studio).&amp;nbsp; ITaskHost is extremely useful in cases where you are hosting the build engine yourself.&amp;nbsp; I will cover the details of this beast in a later post.&lt;/P&gt;
&lt;P&gt;.NET properties on a task type allow you define&amp;nbsp;parameters on the task in order&amp;nbsp;to communicate with the task via the project file.&amp;nbsp; So, in the case of the SetEnvironmentVariable task, I have defined Name and Value properties as inputs into the task. My use of the &lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.requiredattribute.aspx"&gt;Required&lt;/A&gt; attribute on these two properties ensures that the invocation of the tasks will not be possible without specifying those two parameters. In this context, it makes sense because the task cannot perform its function without having those to values specified to it.&lt;/P&gt;
&lt;P&gt;Finally, returning true from the Execute method indicates success to the MSBuild engine. I have ignored the possibility of the task failing in this case to keep it simple - look for more details on this subject alone in a subsequent post.&lt;/P&gt;
&lt;P&gt;Here's how the task is invoked from a project file:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;lt;Project xmlns="&lt;/FONT&gt;&lt;A href="http://schemas.microsoft.com/developer/msbuild/2003"&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;UsingTask AssemblyFile="SimpleTasks.dll" TaskName="SimpleTask.SetEnvironmentVariable" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;PropertyGroup&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;OutputPath&amp;gt;c:\temp&amp;lt;/OutputPath&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/PropertyGroup&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp; &amp;lt;Target Name="MyTarget"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SetEnvironmentVariable Name="OutputPath" value="$(OutputPath)" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/Target&amp;gt;&lt;BR&gt;&amp;lt;/Project&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That's all there is to defining and using custom tasks.&amp;nbsp;Of course, it is way simpler to derive from the abstract class Microsoft.Build.Utilities.Task that is included in the Microsoft.Build.Utilities assembly, and that's what you should be using most of the time unless you require a richer interaction with the MSBuild engine.&lt;/P&gt;
&lt;P&gt;In the next post,&amp;nbsp;I will&amp;nbsp;dig into more details on interacting with tasks via the project file. We will examine the types of objects that can be passed in and out of tasks, caveats to watch out for, etc.&lt;/P&gt;
&lt;P&gt;[ Author: Faisal Mohamood ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=515834" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Faisal+Mohamood/default.aspx">Faisal Mohamood</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Use the AssemblyInfoTask With Source Code Control</title><link>http://blogs.msdn.com/msbuild/archive/2006/01/05/how-to-use-the-assemblyinfotask-with-source-code-control.aspx</link><pubDate>Fri, 06 Jan 2006 01:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:508976</guid><dc:creator>msbuild</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/508976.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=508976</wfw:commentRss><description>&lt;P&gt;Several people have written our feedback alias with problems using the AssemblyInfoTask when the projects are under source code control. When the files are checked in the AssemblyInfo files are read-only, and the task fails with an error that the file can't be updated.&lt;/P&gt;
&lt;P&gt;The best way to handle this is to check the AssemblyInfo files out before running the AssemblyInfoTask. After the build completes you can then either revert the files, or check them back in with the updated version numbers.&lt;/P&gt;
&lt;P&gt;To check the files out and then check them back in using Team Foundation Server add the following lines to your TFSProj file after the &amp;lt;Imports&amp;gt; line for Microsoft.VersionNumber.targets:&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;lt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;AfterGet&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'$(IsDesktopBuild)'!='true'&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Exec&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;WorkingDirectory&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(SolutionRoot)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Command&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;$(TeamBuildRefPath)\..\tf.exe&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;checkout /recursive $(AssemblyInfoFiles)&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;AfterCompile&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'$(IsDesktopBuild)'!='true'&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Exec&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;WorkingDirectory&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(SolutionRoot)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Command&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;$(TeamBuildRefPath)\..\tf.exe&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;checkin /comment:&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;Auto-Build: Version Update&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; /noprompt /override:&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;Auto-Build:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Version Update&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;&amp;amp;quot;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; /recursive $(AssemblyInfoFiles)&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Thanks to Gautam from the Team Build team for this tip!&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=508976" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/AssemblyVersionInfo/default.aspx">AssemblyVersionInfo</category></item><item><title>How To: Retrieve the AssemblyVersion using AssemblyInfoTask</title><link>http://blogs.msdn.com/msbuild/archive/2006/01/04/how-to-retrieve-the-assemblyversion-using-assemblyinfotask.aspx</link><pubDate>Wed, 04 Jan 2006 22:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:509308</guid><dc:creator>msbuild</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/509308.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=509308</wfw:commentRss><description>&lt;P&gt;We got a great question at &lt;A href="mailto:msbuild@microsoft.com"&gt;msbuild@microsoft.com&lt;/A&gt; last week:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;FONT color=#0000ff&gt;What is the preferred method to retrieve the version of the assembly that was just built via MSBuild? Post build, we would like to automatically create and copy the assembly(ies) to version folder.&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;If you are using the &lt;A href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=93d23e13-c653-4815-9e79-16107919f93e"&gt;AssemblyInfoTask&lt;/A&gt; and its associated Microsoft.VersionNumber.Targets file this is really easy. Here's what you do:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;Import&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'"&gt;Project&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;"&lt;SPAN style="COLOR: blue"&gt;$(MSBuildExtensionsPath)\Microsoft\AssemblyInfoTask\Microsoft.VersionNumber.Targets&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;AfterBuild&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;$(MaxAssemblyVersion) != ''&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;MakeDir&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Directories&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;c:\archive\$(AssemblyName)\$(MaxAssemblyVersion)&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;$(OutputPath)\**\*.*&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Output&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;Include&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;FilesToArchive&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Copy&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;SourceFiles&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;@(FilesToArchive)&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DestinationFolder&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;c:\archive\$(AssemblyName)\$(MaxAssemblyVersion)\%(FilesToArchive.RecursiveDir)&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Now that I look at this, perhaps "really easy" isn't the right way to describe it :) In fact, I had to have Faisal show me how to do the &lt;a href="http://blogs.msdn.com/msbuild/archive/2005/11/07/490068.aspx"&gt;recursive copy&lt;/A&gt;, and Kieran help me figure out that a &lt;a href="http://blogs.msdn.com/msbuild/archive/2005/10/04/476725.aspx"&gt;CreateItem&lt;/A&gt; was needed.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The $(MaxAssemblyVersion) property holds the version number for the build. This is used with the &lt;A href="http://msdn2.microsoft.com/en-us/library/s2448zz7.aspx"&gt;MakeDir&lt;/A&gt; task to create the directory. The &lt;A href="http://msdn2.microsoft.com/en-us/library/s2y3e43x.aspx"&gt;CreateItem&lt;/A&gt; task is used to collect all the files from the output directory into an item group so it can then be copied recursively using the &lt;A href="http://msdn2.microsoft.com/en-us/library/3e54c37h.aspx"&gt;Copy&lt;/A&gt; task. Note the use of the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms164313(en-US,VS.80).aspx"&gt;RecursiveDir metadata&lt;/A&gt;, as described in Faisal's post on recursive copy to ensure all the files are copied as a full directory tree into the archive directory.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The condition on AfterBuild prevents the directory from being created if the MaxAssemblyVersion wasn't set during the build. This happens when none of the files changed, and nothing was re-built. Instead of depending on the $(MaxAssemblyVersion) property you could also set up the Inputs and Outputs to the target to be very specific about what file updates will trigger a copy to the archive directory.&lt;/P&gt;
&lt;P&gt;If you're interesed in where $(MaxAssemblyVersion) comes from, it is set by the Microsoft.VersionNumber.Targets file when the AssemblyInfoTask is run. The snippet from the .targets file looks like this:&lt;/P&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;AssemblyInfo&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; [... junk removed for clarity ... ]&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;MaxAssemblyVersion&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;PropertyName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;MaxAssemblyVersion&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;BR&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Output&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;MaxAssemblyFileVersion&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;PropertyName&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;MaxAssemblyFileVersion&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;lt;/&lt;FONT color=#800000&gt;AssemblyInfo&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;This causes the value of the "MaxAssemblyVersion" property on the AssemblyInfo class (the one in .NET code) to get stuck in the MSBuild "MaxAssemblyVersion" property after the task is run. The same thing happens for MaxAssemblyFileVersion.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=509308" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/AssemblyVersionInfo/default.aspx">AssemblyVersionInfo</category></item><item><title>How To: Return Additional Information on Outputs from a Project</title><link>http://blogs.msdn.com/msbuild/archive/2005/12/08/501034.aspx</link><pubDate>Thu, 08 Dec 2005 18:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:501034</guid><dc:creator>msbuild</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/501034.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=501034</wfw:commentRss><description>&lt;P&gt;We got a great question today from an internal team at Microsoft that is working on some custom build process for their specific application:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;FONT color=#0000ff&gt;We have a project whose output is both libraries and header files. What is the best way to return those outputs to the rest of the build process? How can we indicate they are different "types"?&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Let's assume the project in question is getting called via an MSBuild task. What we want is to be able to say something like this:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;MSBuild&lt;/SPAN&gt; &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'"&gt;Projects&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;"&lt;SPAN style="COLOR: blue"&gt;outs.proj&lt;/SPAN&gt;"&lt;/SPAN&gt; &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'"&gt;Targets&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;"&lt;SPAN style="COLOR: blue"&gt;Build&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;Output&lt;/SPAN&gt; &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'"&gt;ItemName&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;"&lt;SPAN style="COLOR: blue"&gt;Outputs&lt;/SPAN&gt;"&lt;/SPAN&gt; &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'"&gt;TaskParameter&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;"&lt;SPAN style="COLOR: blue"&gt;TargetOutputs&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;MSBuild&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;TargetOutputs should contain all of the libraries and headers that were generated. But how do you tell them apart? Kieran replied and pointed out that this is an excellent example of the power of metadata. &lt;/P&gt;
&lt;P&gt;When a task in outs.proj actually generates the output (either header or library) it also tacks on special metadata. The metadata can be anything, but in this example the headers have the “type” metadata set to “header” and the libraries have it set to “library”. The code to do this looks something like:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;this.taskOutput[0].&lt;/FONT&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/microsoft.build.framework.itaskitem.setmetadata.aspx"&gt;&lt;FONT face="Courier New" size=2&gt;SetMetadata&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Courier New" size=2&gt;(“type”, “header”);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;where taskOutput is an array of ITaskItem objects. The great thing about this approach is that you can combine it with batching later in your build process. Let’s say later on you want to print out the list of headers that were generated. The line in the MSBuild file would look like this:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Message&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;"&lt;SPAN style="COLOR: blue"&gt;Returned Headers: @(Outputs)&lt;/SPAN&gt;"&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Condition&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;"&lt;SPAN style="COLOR: blue"&gt;'%(Outputs.Type)' == 'Header'&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; /&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;The best part is that metadata will follow the outputs through the entire build process, not just at batch time. If the outputs in this scenario get passed in to some other task down the line, that task in its implementation can use the object model to query for the metadata and do interesting things.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=501034" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Specify Long Command Lines to MSBuild</title><link>http://blogs.msdn.com/msbuild/archive/2005/11/29/497477.aspx</link><pubDate>Tue, 29 Nov 2005 19:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:497477</guid><dc:creator>msbuild</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/497477.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=497477</wfw:commentRss><description>&lt;P&gt;Sometimes when using MSBuild.exe the command lines can get pretty darn long and hard to manage. This is particularly true if you're using a custom logger that takes parameters. I also ran into some trouble when I was trying to pass an escaped string to the custom logger via the Visual Studio UI for project properties (the string was getting automatically unescaped by VS. Remind you of a &lt;a href="http://blogs.msdn.com/msbuild/archive/2005/10/27/484742.aspx"&gt;recent blog entry&lt;/A&gt;?). The answer to both these problems is to use a response file for the command line parameters.&lt;/P&gt;
&lt;P&gt;Response files are super easy. Just create a text file using your favourite text editor and put all your command line parameters in it. Then when you run MSBuild use the following command:&lt;/P&gt;
&lt;P&gt;msbuild @parameters.txt&lt;/P&gt;
&lt;P&gt;Then MSBuild will read all the command line parameters from the text file, and proceed as usual.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=497477" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item><item><title>How To: Perform Nightly Builds with Team Foundation Server</title><link>http://blogs.msdn.com/msbuild/archive/2005/11/28/497472.aspx</link><pubDate>Mon, 28 Nov 2005 19:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:497472</guid><dc:creator>msbuild</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/msbuild/comments/497472.aspx</comments><wfw:commentRss>http://blogs.msdn.com/msbuild/commentrss.aspx?PostID=497472</wfw:commentRss><description>&lt;P&gt;Edit: Ok, after talking with Khushboo and given Niels's comment, it's clear that the article I linked to is woefully out of date. Please ignore this post. If you want&amp;nbsp;to perform nightly builds with Team Foundation Server, tfsbuild.exe is the tool to use.&lt;/P&gt;
&lt;P&gt;[ Author: Neil Enns ]&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=497472" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/msbuild/archive/tags/Neil+Enns/default.aspx">Neil Enns</category><category domain="http://blogs.msdn.com/msbuild/archive/tags/How+To/default.aspx">How To</category></item></channel></rss>