我在尝试确定为什么MSBuild阻止访问刚刚创建的新T4模板中使用的dll时遇到了很多麻烦。
这个问题很难解释(甚至可以问,标题很明显)。
我创建了一个T4模板来生成一个c#类,它是我们拥有的其他N个类的包装器。这是我提出的解决方案expose multiple WCF Services over the same endpoint。
模板代码本身使用包含各种扩展方法的程序集(Mobiltec.Framework.dll)来简化模板代码。起初,我刚刚将一个.tt文件添加到项目中并继续使用它:每当.tt改变时,它会按预期更新生成的文件。
由于这个模板读取其他程序集并根据它们生成一个类,我想确保它在每个构建中转换输出,以防止开发人员忘记更新输出和类似的东西。
经过几天的搜索,我终于找到了一个相当不错的解决方案,模板正在每个版本上“几乎”完美地转换。问题在于,每当我构建项目并转换模板时,它都会锁定对前面提到的dll的访问,从而阻止我之后删除或更新文件。我必须关闭Visual Studio才能释放文件。
现在,这对本地开发人员机器来说不是一个大问题,但它在构建服务器上的构建失败,因为那里的输出都在一个文件夹中:
这是文本模板系统中的错误还是我可能会犯一些导致文件被锁定的错误?
更新
我会尝试更好地解释一下如何在这里设置一切,以便你们可以更好地理解这个问题。
有一个.tt模板文件,每个Web应用程序一个(共有4个)。此模板负责自动为所有WCF服务合同生成包装类。合同本身在另一个程序集中分开(对于四个组件中的每一个也是一个),以便它们可以与客户端共享,而不会携带所有其他依赖项。
我必须实现一堆方法来使用反射,每个程序集中的签名,成员和类型进行打印,以生成可以编译为有效类的文本。我在一个通用程序集上实现了这些方法。
然后,每个tt文件引用此公共程序集以及服务契约程序集,以生成此包装类。模板有很多这样的行,例如:
<#@ assembly name="Mobiltec.M3.EG.Services.dll" #>
<#@ assembly name="Mobiltec.M3.Common.dll" #>
由于我们需要在每次构建时转换这些模板,因此我更改了项目文件以启用此功能,并在this advice之后安装了Visual Studio SDK和Visualization and Modeling SDK。
现在,每当我对任何程序集或其依赖项中的代码进行任何更改时,我都会收到以下消息:
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
或者:
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
此外,当我尝试通过Visual Studio删除bin / obj文件夹时,我收到此错误:
如果我手动尝试删除bin文件夹上的文件,则在Windows资源管理器中出现此错误:
基本上,这一切都归结为MSBuild在Web应用程序项目的bin文件夹中锁定文件(.tt中所有显式引用的文件)。每当重建项目时,引用的dll都会再次复制到项目自己的输出文件夹中,这会失败,因为Windows无法覆盖“正在使用”的文件。
释放锁的唯一方法是完全关闭Visual Studio并重新打开它。我试图手动杀死机器上的所有MSBuild进程,或关闭并重新打开解决方案,但没有任何作用。即使像Unlocker这样的工具也无法删除文件上的锁(它甚至都没有检测到它)。
构建服务器上的初始问题是由同一个问题引起的,但现在已“解决”,因为我重命名了其中一个dll。两个不同的项目(Mobiltec.Framework.Desktop
和Mobiltec.Framework.WindowsMobile
)具有相同的输出dll名称(Mobiltec.Framework.dll
),第二个项目尝试覆盖构建上的全局输出文件夹中的第一个.tt文件的转换(锁定原始dll)导致整个过程失败。
答案 0 :(得分:4)
稍微相关,谷歌把我带到这里是为了一个非常类似的问题。调试t4模板时,抛出异常会导致T4VSHostProcess.exe
锁定模板中所有引用的DLL。重新启动visual studio修复了问题,但我只能使用sysinternals进程资源管理器并手动终止T4VSHostProcess.exe
进程以避免重启visual studio。
答案 1 :(得分:0)
您使用的是多核构建吗?默认情况下可以启用将msbuild与/ nr:false一起使用。 这是可以强制msbuild锁定文件的功能之一。
答案 2 :(得分:0)
如果我理解正确,这个问题可能已经在VS2010sp1中得到修复,提到here。另一方面,您可能会遇到查找DLL的问题。