I ended up solving this by adding the Project and Solution information in a custom Assembly Attribute (i.e. to the test .dll) at build time, through a custom MSBuild task. Here are roughly the steps I followed (from memory).
First, I created the custom Attribute:
[AttributeUsage(AttributeTargets.Assembly)]
public class ProjectAttribute: Attribute {
public string Project { get; set; }
public string Solution { get; set; }
public ProjectAttribute(string project, string solution)
{
this.Project = project;
this.Solution = solution;
}
}
This custom attribute was defined in an Assembly that was referenced by all unit test projects.
I then created a very simple/rudimentary inline MSBuild task, CreateProjectAttribCs
that would dynamically create an extra C# file with one line. Something like:
[assembly: ProjectAttribute(Project="$(ProjectName)") Solution="$(Solution)"]
And I then added this file to the <Compile>
Item Group, inside a custom MSBuild target called before Compile (again, just going from memory):
<Target Name="CreateProjectAttribCs" BeforeTargets="Compile">
<CreateProjectAttribCs File="ProjectAttribute.cs" />
<ItemGroup>
<Compile Include="ProjectAttribute.cs" />
</ItemGroup>
</Target>
<Target Name="CleanupProjectAttribCs" AfterTargets="Compile>
<Delete Files="ProjectAttribute.cs" />
</Target>
For C++ projects I'd added the Project and Solution info to a String Table resource "injected" in a similar way to the ProjectAttrib.cs
file.
One major annoyance with all of this was that developers would have to add this custom MSBuild .targets
file (which would contain the custom targets and the assembly reference) by editing the .csproj or .vcxproj.
To circumvent that a bit, I also created a custom Visual Studio Project Template for our team's unit tests so that everything was already added and my fellow devs would never have to see the innards of an MSBuild project.
The hardest part was adding the Project/Solution info. Once I had that it was easy to read the custom attributes on the test assemblies or String Table resource in a native .dll, and add the info to data parsed/transformed from the test results to a custom test result database and report.