I have finally managed to perform automatically the copy from Project B without having to modify it. IIya was not so far from the solution, but the fact is that I cannot generate statically as the list of files to generate from Project A with MyCustomTask is dynamic. After digging more into Microsoft.Common.targets
, I have found that ProjectB will get the list of output from Project A by calling the target GetCopyToOutputDirectoryItems
. This target is dependent from AssignTargetPaths
which itself is dependent on the target list property AssignTargetPathsDependsOn
.
So in order to generate dynamically content and to get this content being copied automatically through standard project dependency, we need to hook Project A at two different places:
- In
AssignTargetPathsDependsOn
as it is called indirectly by Project B on Project A through GetCopyToOutputDirectoryItems. And also it is indirectly called by Project A when PrepareResource
is called. Here, we are just outputing the list of files that will be generated (by Project A) or consumed by Project B. AssignTargetPathsDependsOn will call a custom task MyCustomTaskList
which is only responsible to output the list of files (but not to generate them), this list of files will create dynamic "Content" with CopyOutputDirectory
.
- In
BuildDependsOn
in order to actually generate the content in Project A. This will call MyCustomTask
that will generate the content.
All of this was setup like this in ProjectA:
<UsingTask TaskName="MyCustomTask" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>
<UsingTask TaskName="MyCustomTaskList" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>
<PropertyGroup>
<BuildDependsOn>
MyCustomTaskTarget;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTaskTarget">
<MyCustomTask
ProjectDirectory="$(ProjectDir)"
IntermediateDirectory="$(IntermediateOutputPath)"
Files="@(MyCustomFiles)"
RootNamespace="$(RootNamespace)"
>
</MyCustomTask>
</Target>
<PropertyGroup>
<AssignTargetPathsDependsOn>
$(AssignTargetPathsDependsOn);
MyCustomTaskListTarget;
</AssignTargetPathsDependsOn>
</PropertyGroup>
<Target Name="MyCustomTaskListTarget">
<MyCustomTaskList
ProjectDirectory="$(ProjectDir)"
IntermediateDirectory="$(IntermediateOutputPath)"
Files="@(MyCustomFiles)"
RootNamespace="$(RootNamespace)"
>
<Output TaskParameter="ContentFiles" ItemName="MyCustomContent"/>
</MyCustomTaskList>
<ItemGroup>
<Content Include="@(MyCustomContent)" KeepMetadata="Link;CopyToOutputDirectory"/>
</ItemGroup>
</Target>
This method is working with anykind of C# projects that is using Common.Targets (so It is working with pure Desktop, WinRT XAML App or Windows Phone 8 projects).