6
votes

I am writing a MSBuild task that adds some code generation to a standard C# project (.csproj). The task needs to access types in assemblies referenced by that project.

This is simple for assembly references (get all items in <Reference>), but it gets harder for references to other projects (<ProjectReference>)

Does MSBuild provide a way to retrieve a compiled assembly reference from a <ProjectReference>?

If not, is there a simple way to resolve that name by reading the .csproj file?

The .csproj file does not directly provide the compiled assembly path, it has to be reconstructed from other properties. Also, some of the properties are conditional (depending on Debug/Release configuration), so using a simple XPath reader wouldn't work:

Dll file name can be obtained from <AssemblyName>, but the path where the Dll file is written is in

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <OutputPath>;bin\Release</OutputPath>
<PropertyGroup>

Is there a way to programmatically read the .csproj file and resolve the correct value of OutputPath by evaluating all conditions?

I need a solution where the referenced .csproj files remain plain old project files (no modifications to the csproj files that would add the necessary information in a more accessible way)

1

1 Answers

7
votes

You could put something like:

<Target Name="CopyDllsFromDependentProjects">
<MSBuild Projects="@(ProjectReference)" Targets="Build" BuildInParallel="true" Condition="'%(Name)'=='ProjectA' Or '%(Name)'=='ProjectB'">
  <Output TaskParameter="TargetOutputs" ItemName="OutputAssemblies" />
</MSBuild>
<Copy SourceFiles="@(OutputAssemblies)" DestinationFolder="$(PostBuildDir)" SkipUnchangedFiles="true" />

in to your project and call it like this:

 <Target Name="AfterCompile" DependsOnTargets="CopyDllsFromDependentProjects" />

Add seasoning to taste.

This involves MSBuilding the dependencies to work out the outputs (the info cant statically be derived due to the way in which inclusions are processed in MSBuild - e.g., where would TeamBuild put the outputs?).

The Inside the MSBuild Engine book is great for digging into this sort of nonsense.