MSBuild locking dll used on T4 template generated on build
Asked Answered
J

3

11

I'm having a lot of trouble trying to identify why MSBuild is blocking access to a dll used inside a new T4 template I just created.

The problem is kind of hard to explain (and even ask, as is evident by the title).

I created a T4 template to generate a c# class that is a wrapper to N other classes we have. This was the solution I came up with to expose multiple WCF Services over the same endpoint.

The template code itself uses an assembly (Mobiltec.Framework.dll) that contains various extension methods to simplify the template code. At first, I just added a .tt file to the project and went with it: it updated the generated file whenever the .tt changed, as expected.

Since this template reads other assemblies and generates a class based on them, I wanted to make sure it transformed the output on every build, as to prevent developers from forgetting to update the output and things like that.

After a few days of searching, I finally came to a fairly decent solution and the templates were being transformed on each build 'almost' perfectly. The problem is that, whenever I build the project and the template is transformed, it locks access to the aforementioned dll, preventing me from deleting or updating the file afterwards. I have to close Visual Studio for it to release the file.

Now, this is not a huge problem on local developers machines, but it fails our build on the build server because the output there is all in a single folder:

  1. The build process starts compiling our master solution
  2. The project containing the T4 template is compiled, and the class is generated
  3. Another project is compiled and tries to change the dll in the output folder, failing the build after trying 10 times

Is this a bug in the Text Templating system or am I possibly making some mistake that is causing the file to be locked?

Update

I'll try to explain a bit better how everything is setup here, so that maybe you guys can have a better understanding of the problem.

There is a .tt template file, one for each of our web applications (there are 4 in total). This template is responsible for automatically generating a wrapper class for all of our WCF services contracts. The contracts themselves are separated in another assembly (also one for each of the four components) so that they can be shared with clients, without carrying all the other dependencies.

I had to implement a bunch of methods to print, using reflection, the signatures, members and types from each assembly, to generate text that could compile as a valid class. I implemented these methods on a common assembly.

Each tt file then references this common assembly, along with the service contracts assembly, to generate this wrapper class. The template has a bunch of lines like these for instance:

<#@ assembly name="Mobiltec.M3.EG.Services.dll" #>
<#@ assembly name="Mobiltec.M3.Common.dll" #>

Since we need these templates to be transformed on every build, I've changed the project files to enable this and installed the Visual Studio SDK and Visualization and Modeling SDK, following this advice.

Now, whenever I make any changes to code in any of the assemblies or their dependencies, I get messages like these:

Error   1516    Compiling transformation: Metadata file 'Mobiltec.M3.EG.Services.dll' could not be found. Line=0, Column=0  Mobiltec.M3.EG
Error   1517    Compiling transformation: Metadata file 'Mobiltec.M3.Common.dll' could not be found. Line=0, Column=0   Mobiltec.M3.EG

Or:

Error   395 Could not copy "D:\TFS05\M3\Desenvolvimento\Feature-ODataM3S\ProjetosManutencao\Mobiltec.M3.Common\Mobiltec.M3.Common.Desktop\bin\Mobiltec.M3.Common.dll" to "bin\Mobiltec.M3.Common.dll". Exceeded retry count of 10. Failed.  Mobiltec.M3.EG
Error   396 Unable to copy file "D:\TFS05\M3\Desenvolvimento\Feature-ODataM3S\ProjetosManutencao\Mobiltec.M3.Common\Mobiltec.M3.Common.Desktop\bin\Mobiltec.M3.Common.dll" to "bin\Mobiltec.M3.Common.dll". The process cannot access the file 'bin\Mobiltec.M3.Common.dll' because it is being used by another process.    Mobiltec.M3.EG
Error   407 Could not copy "D:\TFS05\M3\Desenvolvimento\Feature-ODataM3S\ProjetosManutencao\Mobiltec.M3.EG\Mobiltec.M3.EG.Services\bin\Debug\Mobiltec.M3.EG.Services.dll" to "bin\Mobiltec.M3.EG.Services.dll". Exceeded retry count of 10. Failed. Mobiltec.M3.EG
Error   408 Unable to copy file "D:\TFS05\M3\Desenvolvimento\Feature-ODataM3S\ProjetosManutencao\Mobiltec.M3.EG\Mobiltec.M3.EG.Services\bin\Debug\Mobiltec.M3.EG.Services.dll" to "bin\Mobiltec.M3.EG.Services.dll". The process cannot access the file 'bin\Mobiltec.M3.EG.Services.dll' because it is being used by another process.  Mobiltec.M3.EG

Also, when I try to delete the bin/obj folders though Visual Studio, I get this error:

Visual Studio Deletion error

If I manually try to delete the files on the bin folder, in Windows Explorer, I get this error:

Windows Explorer Deletion error

Basically, it all boils down to MSBuild locking the files (all of the explicitly referenced ones in the .tt) in the bin folders of the web application projects. Whenever the project is rebuilt, the referenced dlls are copied to the project's own output folder again, and this fails since windows cannot overwrite the files that are 'in use'.

The only thing that releases the lock is completely closing down Visual Studio and reopening it. I tried manually killing all MSBuild processes on the machine, or closing and reopening the solution, but nothing works. Even tools like Unlocker are unable to remove the lock on the files (it doesn't even detect it).

The initial problem on the build server was caused by the very same issue, but is now 'solved' because I renamed one of the dlls. Two different projects (Mobiltec.Framework.Desktop and Mobiltec.Framework.WindowsMobile) had the same output dll name (Mobiltec.Framework.dll), and the second one was trying to overwrite the first on the global output folder on the build, after the transformation took place for the .tt files (locking the original dll) failing the whole process.

Jehovah answered 10/10, 2013 at 22:39 Comment(5)
Maybe I'm missing something but if the .dll contains helper methods why would another project attempt to change the .dll in the output folder?Galenism
How exactly does the template "reads other assemblies"?Slog
@MikeBeeler I've updated the question with more in depth information, please take a look.Jehovah
@NicoleCalinoiu I've updated the question with more in depth information, please take a look.Jehovah
Ugh! Visual Studio locking files you're working on is soooo 2002. I used to get so mad back then because it was a constant battle - I'd slam my office door and pieces of the ceiling would fall down.Psychosomatic
P
8

Slightly related, google brought me here for a very similar problem. Debugging a t4 template, when an exception is thrown causes the T4VSHostProcess.exe to lock all referenced DLLs in the template. Restarting visual studio fixed the problem, but I was able to just use sysinternals process explorer and manually kill the T4VSHostProcess.exe process to avoid restarting visual studio.

Prakrit answered 22/2, 2016 at 15:55 Comment(0)
G
0

Are you using multi core build? May be enabled by default Use msbuild with /nr:false. This is one of those features that can force msbuild to lock files.

Galenism answered 12/11, 2013 at 18:52 Comment(4)
Where do I set this in Visual Studio? Also, isn't there a way to prevent the locking in the first place? I assume I'll lose out on build times if I do this, right?Jehovah
I just remembered seeing this before. 'nr' stands for 'Node Reuse' right? Where the instances of MSBuild are preserved for a set amount of minutes before being taken down to improve performance. I tried enabling this (via an environment variable) before to no avail.Jehovah
After looking into this issue more seems that it can be caused even when single threaded. Known issue with Microsoft article here as to identification of the actual locking process. blogs.technet.com/b/markrussinovich/archive/2005/04/24/…Galenism
Unfortunately, the problem in the article you linked seems completely unrelated to my actual problem here. In my case, it is completely deterministic: every time I change the files, MSBuild locks the dlls. It's not something that happens only a few times or under certain random conditions.Jehovah
S
0

If I understand you correctly this problem might have been fixed in VS2010sp1 a mentioned here. On the other hand you might get a problem with finding the DLL.

Supersonics answered 2/12, 2015 at 13:31 Comment(3)
That fix is from December 2010. When I asked the question (a long time ago) I was using a much more up-to-date Visual Studio version than that, so I think it is not related, unfortunately.Jehovah
Running VS2017 (15.9.5) and still experiencing the same issue. 'Debug T4 Template' locks assemblies after debug session (with exception). [2c]Lil
I'm on 2022 here and still happens. Trying to dotnet build outside of VS and it hangs because project output ref'd by the TT is locked.Luo

© 2022 - 2024 — McMap. All rights reserved.