MSBuild’s Fix

I was reading John Lam‘s excellent A Practical Developers’ Guide to MSBuild article which is contained in the second installment of his Practical Eye for the .NET Guy newsletter when I realized that this could be a great opportunity to try out my Object Model Generator on MSBuild’s project files. This could be a first step towards the creation of a tool that edits these files.

I took the msbuild.xsd schema that came with Visual C# 2005 Express Edition Beta 1 and dumbed it down a little to this version, so that the current version of OMG could handle it. I ran it through OMG to get this output.
Let’s look a little bit at how to work with what we got.

I took John’s example of a valid project file:

<Project DefaultTargets="Build">

    <PropertyGroup>
        <Property DebugSymbols="True"/>
        <Property Optimize="False"/>
        <Property OutputType="exe"/>
    </PropertyGroup>

    <ItemGroup>
        <Item Type="Compile" Include="App.cs"/>
    </ItemGroup>

    <Target Name="Build">
        <Task Name="Csc"
            Sources="@(Compile)"
            EmitDebugInformation="$(DebugSymbols)"
            Optimize="$(Optimize)"
            DefineConstants="DEBUG"
            TargetType="$(OutputType)"/>
    </Target>

</Project>

The example gives us a couple of the features exposed by MSBuild.

Now let’s see how this structure is achieved by means of using the code generated by OMG:

ProjectElement project = new ProjectElement();

ProjectElement.PropertyGroupElement propGroup =
    new ProjectElement.PropertyGroupElement();

ProjectElement.PropertyGroupElement.PropertyElement debugSymbols = new
    ProjectElement.PropertyGroupElement.PropertyElement();
debugSymbols.CustomAttributes.Add("DebugSymbols", "True");
propGroup.Propertys.Add(debugSymbols);

ProjectElement.PropertyGroupElement.PropertyElement optimize =
    new ProjectElement.PropertyGroupElement.PropertyElement();
optimize.CustomAttributes.Add("Optimize", "False");
propGroup.Propertys.Add(optimize);

ProjectElement.PropertyGroupElement.PropertyElement outputType =
    new ProjectElement.PropertyGroupElement.PropertyElement();
outputType.CustomAttributes.Add("OutputType", "exe");
propGroup.Propertys.Add(outputType);

project.PropertyGroups.Add(propGroup);

ProjectElement.ItemGroupElement itemGroup =
    new ProjectElement.ItemGroupElement();

ProjectElement.ItemGroupElement.ItemElement item =
    new ProjectElement.ItemGroupElement.ItemElement();
item.Include = "App.cs";
item.CustomAttributes.Add("Type", "Compile");
itemGroup.Items.Add(item);

project.ItemGroups.Add(itemGroup);

ProjectElement.TargetElement target =
    new ProjectElement.TargetElement();

target.Name = "Build";

ProjectElement.TargetElement.TaskElement cscTask =
    new ProjectElement.TargetElement.TaskElement();

cscTask.CustomAttributes.Add("Name", "Csc");
cscTask.CustomAttributes.Add("Sources", "@(Compile)");
cscTask.CustomAttributes.Add("EmitDebugInformation", "$(DebugSymbols)");
cscTask.CustomAttributes.Add("Optimize", "$(Optimize)");
cscTask.CustomAttributes.Add("DefineConstants", "DEBUG");
cscTask.CustomAttributes.Add("TargetType", "$(OutputType)");

target.Tasks.Add(cscTask);

project.Targets.Add(target);

ProjectDocument doc = ProjectDocument.FromDOM(project);

doc.Save("c:\\app.proj");

Let’s examine the code brought here.
First, we create the root Project element. We then create a PropertyGroup element that contains the three Property elements we need. Note that these properties are untyped and as such can not have members declared for them.
Next comes the ItemGroup element which contains an Item element. The Include attribute was already declared and as such, a property on the Item class was generated for it.
The last two lines translate our typed DOM to an XmlDocument and then save it to a file with the creative name app.proj.
Needless to say, the output file is similar to the file we wished to create.

The next step would be to build a graphical user interface for this, binding properties to fields, etc.
I’d love to see that happen. :)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s