Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

T4: using properties in both Visual Studio and MSBuild

I am having trouble creating a T4 template that can be used to generate a relatively simple C# code both from Visual Studio and from MSBUild. The template references a DLL, which resides in the output path of the project. Apart from that, it is a fairly simple template that loops through a collection of domain objects and outputs a test method for each of them.

MSDN suggests the following approach for using properties in both hosts:

<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
    <myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>

<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
    <T4ParameterValues Include="myLibFolder">
      <Value>$(myLibFolder)</Value>
    </T4ParameterValues>
  </ItemGroup>

Unfortunately, this just does not work. When executing via MSBuild, I get the following error:

Compiling transformation: Metadata file '$(myLibFolder)Cmc.SpeedWays.Core.Testing.dll' could not be found   

Did anybody manage to solve this problem or at least find an acceptable workaround? We are using VS2012 and MSBUild 4.0.

like image 230
Boris Mesetovic Avatar asked Nov 11 '22 08:11

Boris Mesetovic


1 Answers

I had the same problem and am sorry to say that I did not get a single obvious fix. However the problem did go away, it seems like a collection of possible issues.

I think the key one was this type of property declaration only works if you build the solution/project with MSBuild, if you use Visual Studio the properties will be null. I think this was the confusion for me. In the end I ended up with calls in my template, where I try to get the MSbuild declared property, and if this fails as VS

var configName = Host.ResolveParameterValue("-", "-", "configuration");
if (String.IsNullOrEmpty(configName)==true)
{
    WriteLine ("// Generated from Visual Studio");
    IServiceProvider serviceProvider = (IServiceProvider)this.Host;
    DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;  
    configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name ;
}

Other thing to watch out for is building invalid strings with string concatenation, easy to end up with a null

like image 50
Richard Fennell Avatar answered Nov 15 '22 07:11

Richard Fennell