Bite-sized reusable MSBuild targets, properties and tasks

I’m a long-time MSBuild fan. Now that it’s open source, I’ve even played with bootstrapping it with xbuild to use it even on Mac. It works like a charm, for the most part :)

I’ve always wished I could just reuse fragments of MSBuild targets that are generic enough to fit in lots of projects. Things like determining whether we’re being built with XBuild or MSBuild, determining the location of Git, or the particular assembly location for a CodeTaskAssembly (which isn’t exactly trivial). Those kinds of things are probably a few lines of XML that could even be distributed via NuGet.

And so I started doing just that for my own stuff, and thus MSBuilder was born. It is sort of like NetFx but for MSBuild rather than .NET code. It may still suffer from that project’s Achilles heel though, namely, discoverability. But with any luck, the extremely low barrier of entry for contributors, plus the almost real-time pull-request building and subsequent nuget publishing, thanks to a paid super-responsive AppVeyor-based CI system, will make it useful enough to gain traction. Time will tell.

In the meantime, I’ve already added a few very useful MSBuilder blocks already:

Package Stats
MSBuilder.CodeTaskAssembly NuGet downloads Version
MSBuilder.DownloadFile NuGet downloads Version
MSBuilder.DumpItems NuGet downloads Version
MSBuilder.Git NuGet downloads Version
MSBuilder.Introspect NuGet downloads Version
MSBuilder.IsXBuild NuGet downloads Version
MSBuilder.NuGet.GetLatestVersion NuGet downloads Version
MSBuilder.RegexReplace NuGet downloads Version
MSBuilder.Run NuGet downloads Version
MSBuilder.TaskInliner NuGet downloads Version
MSBuilder.ThisAssembly.Project NuGet downloads Version

MSBuilder.DumpItems

One of my most frequently used ones is surely MSBuilder.DumpItems. Whenever I’m tweaking MSBuild targets, especially if they are the built-in ones in either MSBuild/CSharp itself, or WiX, I more often than not want to inspect what various item groups contain at certain points, as well as potentially useful item metadata I might want to use for my task at hand.

For example, say you want to do something interesting with project references that requires you to know precisely what’s going on in the built-in targets after project and assembly references are resolved. You can just create a console app, install the package

install-package MSBuilder.DumpItems

and edit the .csproj to dump items on AfterBuild for inspection of the items built by one of the many targets involving ResolveReferences, such as the _ResolvedProjectReferencePaths which looks kinda interesting:

<Target Name="AfterBuild">
  <DumpItems Items="@(_ResolvedProjectReferencePaths)" />
</Target>

And you get a full dump of all those items and their metadata, right in the Visual Studio output window, such as:

2>AfterBuild:
2>  Item: C:\Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.dll
2>  	AccessedTime=2015-07-19 01:18:52.2170776
2>  	BuildReference=true
2>  	Configuration=Debug
2>  	CreatedTime=2015-07-19 01:16:15.3999053
2>  	DefiningProjectDirectory=C:\Program Files (x86)\MSBuild\12.0\bin\
2>  	DefiningProjectExtension=.targets
2>  	DefiningProjectFullPath=C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets
2>  	DefiningProjectName=Microsoft.Common.CurrentVersion
2>  	Directory=Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\bin\Debug\
2>  	Extension=.dll
2>  	Filename=ClassLibrary1
2>  	FullConfiguration=Debug|AnyCPU
2>  	FullPath=C:\Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.dll
2>  	Identity=C:\Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.dll
2>  	ModifiedTime=2015-07-19 01:18:52.2070760
2>  	MSBuildSourceProjectFile=C:\Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\ClassLibrary1.csproj
2>  	MSBuildSourceTargetName=GetTargetPath
2>  	Name=ClassLibrary1
2>  	OriginalItemSpec=..\ClassLibrary1\ClassLibrary1.csproj
2>  	OriginalProjectReferenceItemSpec=..\ClassLibrary1\ClassLibrary1.csproj
2>  	OutputItemType=
2>  	Platform=AnyCPU
2>  	Project={e9288a56-aa1b-4127-97c5-7b3a6d487d63}
2>  	RecursiveDir=
2>  	ReferenceOutputAssembly=true
2>  	ReferenceSourceTarget=ProjectReference
2>  	RelativeDir=C:\Delete\ConsoleApplication13\src\ConsoleApplication1\ClassLibrary1\bin\Debug\
2>  	RootDir=C:\
2>  	SetConfiguration=Configuration=Debug
2>  	SetPlatform=Platform=AnyCPU
2>  	Targets=
2>
2>Build succeeded.

As I come across more useful bits of MSBuild that are generic enough that deserve becoming MSBuilder blocks, I’ll surely publish them, so stay tunned.

Enjoy!