MSBuild custom task and assembly locks

Hi folks

Sometimes you may want to perform some operations during build which are impossible or at least too difficult to perform using vanilla MSBuild.

For that purpose you may want to use custom task.

The simplest usage would look like

<UsingTask
  TaskName="MyCoolAssembly.MyCoolTask" 
  AssemblyFile="MyCoolAssembly.dll"
/>
<Target
  Name="MyCoolTarget">
  <MyCoolTask />
</Target>

It can be made more complex and pass addition parameters and even define output parameters. But there is not a topic of this blogpost. Read MSBuild documentation if you want to know more.

I would like to discuss one thing that annoys me.

MSBuild loads custom assembly dll into its main AppDomain and therefore this assembly becomes locked until MSBuild exited. So by default after compilation completed MyCoolAssembly.dll couldn’t be removed until Visual Studio (or command prompt) reopened.

There are some workarounds you may find in questions like this http://stackoverflow.com/questions/13510465/the-mystery-of-stuck-inactive-msbuild-exe-processes-locked-stylecop-dll-nuget

But I’d prefer a solution which would work regardless of the way MSBuild called.

And recently I invented a way to solve this problem

<PropertyGroup>
  <TempFolder>$([System.IO.Path]::GetTempPath())$([System.Guid]::NewGuid())</TempFolder>
</PropertyGroup>
<Target
  Name="CopyTaskAssemblyToTempFolder"
  BeforeTargets="BeforeBuild">
  <Copy
    SourceFiles="$(MSBuildThisFileDirectory)MyCoolAssembly.dll"
    DestinationFolder="$(TempFolder)"
  />
</Target>
<UsingTask
  TaskName="MyCoolAssembly.MyCoolTask" 
  AssemblyFile="$(TempFolder)\MyCoolAssembly.dll"
/>
<Target
  Name="MyCoolTarget">
  <MyCoolTask />
</Target>

Here my dll is being copied to the unique temp folder and then loaded and executed from there.

Well, ideally the dll should be removed after execution but to mark dll for deletion we’ll need to P/Invoke MoveFileEx which is too complicated to put into MSBuild script. So my solution will litter into the temp folder a bit but I think it is not that big deal.

Stay tuned

Advertisements

About mnaoumov

Senior .NET Developer in Readify
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

6 Responses to MSBuild custom task and assembly locks

  1. Bas says:

    Hi Mnaoumov, a very very very big thank you for you. Been pulling my hair out for quite a while. Found a lot of “workarounds” on stackoverflow, but this one is absolutely brilliant! Thx, keep up the good work!

  2. mnaoumov says:

    Thanks @Bas, I glad this works for you. I am planning for a long time to implement proper deletion and FileListAbsolute.txt

  3. Thanks for this great idea!

    I modified it slightly to use the intermediate object folder as the base folder, rather than the user’s temp path, i.e. $(IntermediateOutputPath) instead of $([System.IO.Path]::GetTempPath()).

    I also removed the temp folder and copied DLL afterwards by just calling RemoveDir task after the build, i.e.:

  4. Looks like it ate up the XML from my previous comment… However, it’s simply a case of adding the RemoveDir task to the “AfterBuild” Target with the $(TempFolder) as the Directories argument 🙂

    • Disregard that, for some reason it appeared to work a couple of times, but it won’t typically work due to the original DLL locking problem.

      • mnaoumov says:

        Hi Peet. I just was about to say the same regarding deletion. In order to implement it properly we have to PInvoke some MoveFileEx which is a bit verbose to do in a plain MSBuild.

        I’ve also considered $(IntermediateOutputPath). I had however some isssues with the tasks that has to be executed on the very early build steps before BeforeBuild. I had $(IntermediateOutputPath) empty.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s