1

I'm trying to develop a custom MSBuild task and test it by invoking it from another project in the same solution. Originally I set up UsingTask in the test project to reference the .dll in the task project:

<UsingTask TaskName="FooTask" AssemblyFile="..\Task\bin\$(Configuration)\Task.dll"/>
<Target Name="RunFooTask" BeforeTargets="Compile">
    <FooTask/>
</Target>

This mostly works. But frequently and seemingly at random, building the test project leaves the task project .dll locked by MSBuild and/or Visual Studio, which requires killing the rogue MSBuild process and restarting Visual Studio. This sounds similar to Visual Studio 2008 locks custom MSBuild Task assemblies and Visual Studio 2008 locks dll in bin folder and doesn't let go of it. But my task is already an AppDomainIsolatedTask and I've tried setting GenerateResourceNeverLockTypeAssemblies. This does not solve the problem.

So I tried adding a project reference from the test project to the target project, thinking it would copy the .dll into the test project and UsingTask could find it there:

<UsingTask TaskName="FooTask" AssemblyFile="$(OutputPath)Task.dll" />

This seems to solve the problem with the .dll being left locked. The problem now is that the .dll has not been copied yet when the task is invoked. If I understand correctly, BeforeTargets="Compile" means any time before compile, not necessarily immediately before compile. So I think I need to also specify AfterTargets with whatever target copies the .dll from the referenced project. What target would that be?

Incidentally, I also tried changing BeforeTargets="Compile" to BeforeTargets="Build". Now the .dll is copied before the task runs, but that's because it runs after the build! I boiled this down to a test target that doesn't involve UsingTask at all:

<Target Name="Hello" BeforeTargets="Build">
    <Message Importance="high" Text="Hello" />
</Target>

Output:

1>------ Rebuild All started: Project: Test, Configuration: Debug Any CPU ------
1>  Test -> C:\[redacted]\MSBuildTest2\Test\bin\Debug\Test.exe
1>  Hello

This makes me doubt everything I thought I knew about what's going on.

StackOverthrow
  • 1,158
  • 11
  • 23
  • Do you need to run before compile? Usually you'd develop these tasks in a way that doesn't require referencing them from VS because of this reason. – Martin Ullrich Nov 26 '18 at 22:56
  • @MartinUllrich It's a code generator, so yes. – StackOverthrow Nov 27 '18 at 00:07
  • If you don't want it to lock VS, I suggest splitting the solutions and trying to build a NuGet Package / SDK package containing the task + targets along with integration tests that invoke MSBuild itself, then use the NuGet package in the project you want to use code generation from inside VS. Nevertheless, I suggest importing the file via a direct path since references are copied AFTER compilation – Martin Ullrich Nov 27 '18 at 00:11
  • @MartinUllrich I packaged the task as a NuGet package and installed it in the project that needs to use it. This has the same effect as a project reference: the .dll does not exist in `$(OutputDir)` until after the build. In other build systems it would be a compile scope dependency, but MSBuild apparently has no concept of that. I also expected `UsingTask` to be able to use `AssemblyName` instead of `AssemblyFile` when consuming a NuGet package, but that doesn't work, either. Perhaps I don't understand the correct usage of `AssemblyName`. – StackOverthrow Nov 27 '18 at 00:23
  • Maybe a MSBuild task is entirely the wrong thing to use for this purpose. I originally wrote my code generator as a console app, but I thought a build task would be less hacky. – StackOverthrow Nov 27 '18 at 00:27
  • Both work. but I'd ship an msbuild target inside the NuGet package to reference it. The task wouldn't be packaged as dll to be referenced but into a special directory with the msbuild targets referencing it from there. you can see an example at https://github.com/dasMulli/AssemblyInfoGenerationSdk – Martin Ullrich Nov 27 '18 at 01:13
  • @MartinUllrich Is this what you're talking about: [Bundling .NET build tools in NuGet](https://natemcmaster.com/blog/2017/11/11/build-tools-in-nuget/)? I would accept an answer that says this is an XY problem and I'm doin' it wrong. – StackOverthrow Nov 27 '18 at 17:35

0 Answers0