2013-10-10 4 views
7

У меня много проблем, пытаясь определить, почему MSBuild блокирует доступ к dll, используемому в новом шаблоне T4, который я только что создал.MSBuild блокировка dll, используемая на шаблоне T4, сгенерированная на сборке

Проблема довольно трудно объяснить (и даже спросить, как видно из названия).

Я создал шаблон T4 для создания класса C#, который является оболочкой для N других классов, которые у нас есть. Это было решение, которое я придумал для expose multiple WCF Services over the same endpoint.

Сам код шаблона использует сборку (Mobiltec.Framework.dll), которая содержит различные методы расширения, чтобы упростить код шаблона. Сначала я просто добавил файл .tt в проект и пошел с ним: он обновил сгенерированный файл всякий раз, когда изменился .tt, как и ожидалось.

Поскольку этот шаблон читает другие сборки и генерирует на их основе класс, я хотел бы убедиться, что он преобразует вывод в каждую сборку, чтобы не забывать разработчики обновлять выходные данные и тому подобное.

После нескольких дней поиска я наконец пришел к довольно приличному решению, и шаблоны трансформировались на каждой сборке «почти» отлично. Проблема заключается в том, что всякий раз, когда я создаю проект, и шаблон преобразуется, он блокирует доступ к вышеупомянутой dll, не позволяя мне впоследствии удалять или обновлять файл. Мне нужно закрыть Visual Studio, чтобы он выпустил файл.

Теперь, это не большая проблема на локальных компьютерах разработчиков, но он не наш билд на сервере сборки, поскольку выход есть все в одной папке:

  1. Процесс сборки начинается составление нашего мастера решение
  2. проект, содержащий шаблон T4 компилируется и генерируется класс
  3. Другой проект компилируется и пытается изменить DLL в папке вывода, в противном случае сборки после попытки 10 раз

Является ли это ошибкой в ​​системе текстовых шаблонов или я могу ошибиться, что заставляет файл блокироваться?

Update

Я попытаюсь объяснить немного лучше, как все настроено здесь, так что, возможно, вы, ребята, может иметь более глубокое понимание проблемы.

Файл шаблона .tt, по одному для каждого нашего веб-приложения (всего 4). Этот шаблон отвечает за автоматическое создание класса-оболочки для всех наших контрактов услуг WCF. Сами контракты разделяются в другой сборке (также по одному для каждого из четырех компонентов), чтобы они могли делиться с клиентами, не перенося все другие зависимости.

Я должен был реализовать множество методов для печати, используя отражение, подписи, элементы и типы из каждой сборки, чтобы сгенерировать текст, который мог бы скомпилироваться как действительный класс. Я реализовал эти методы на общей сборке.

Каждый файл tt ссылается на эту общую сборку вместе с сборкой контрактов на обслуживание для создания этого класса-оболочки.Шаблон имеет кучу линий, как это например:

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

Поскольку нам нужны эти шаблоны должны быть трансформированы в каждой сборке, я изменил файлы проект, чтобы включить это и установил Visual Studio SDK и визуализацию и Моделирование SDK, следуя this advice.

Теперь, когда я делаю какие-либо изменения в код в любом из сборок или их зависимостей, я получаю сообщение, подобное этим:

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 

Кроме того, когда я пытаюсь удалить бен/OBJ папки, хотя Visual Studio, я получаю эту ошибку:

Visual Studio Deletion error

Если я вручную попытаться удалить файлы в папке BIN, в Windows Explorer, я получаю эту ошибку:

Windows Explorer Deletion error

В принципе, все это сводится к MSBuild блокировки файлов (все из явно ссылаются те, в .tt) в папках bin проектов веб-приложений. Всякий раз, когда проект перестраивается, ссылающиеся DLL снова копируются в собственную выходную папку проекта, и это терпит неудачу, поскольку Windows не может перезаписывать файлы, которые «используются».

Единственное, что освобождает замок, - это полностью закрыть Visual Studio и снова открыть его. Я попытался вручную убить все процессы MSBuild на машине или закрыть и снова открыть решение, но ничего не работает. Даже такие инструменты, как Unlocker, не могут удалить блокировку файлов (это даже не обнаруживает).

Исходная проблема на сервере сборки была вызвана той же самой проблемой, но теперь «решена», потому что я переименовал одну из DLL. Два разных проекта (и Mobiltec.Framework.WindowsMobile) имели одинаковое имя выходного dll (Mobiltec.Framework.dll), а второе пыталось перезаписать первое в глобальной выходной папке сборки после того, как было выполнено преобразование для файлов .tt (блокировка оригинальная dll), не выполняющая весь процесс.

+0

Возможно, мне что-то не хватает, но если .dll содержит вспомогательные методы, почему другой проект попытается изменить .dll в выходной папке? –

+0

Как именно шаблон «читает другие сборки»? –

+0

@MikeBeeler Я обновил вопрос с более подробной информацией, пожалуйста, взгляните. – julealgon

ответ

0

Вы используете многоядерную сборку? Может быть включено по умолчанию Использовать msbuild с/nr: false. Это одна из тех функций, которые могут заставить msbuild блокировать файлы.

+0

Где я могу установить это в Visual Studio? Кроме того, разве нет способа предотвратить блокировку в первую очередь? Я предполагаю, что проиграю в сборку, если я это сделаю, не так ли? – julealgon

+1

Я только что вспомнил, что видел это раньше. «nr» означает «Node Reuse»? Если экземпляры MSBuild сохраняются в течение заданного количества минут, прежде чем их снимать для повышения производительности. Я попытался включить это (через переменную окружения), прежде чем ничего не получилось. – julealgon

+0

После изучения этой проблемы больше кажется, что она может быть вызвана даже при однопоточности. Известная проблема с статьей Microsoft здесь относительно идентификации фактического процесса блокировки. http://blogs.technet.com/b/markrussinovich/archive/2005/04/24/the-case-of-the-mysterious-locked-file.aspx –

0

Если вы правильно поняли эту проблему, то может были исправлены в VS2010sp1 упомянутом here. С другой стороны, у вас может возникнуть проблема с поиском DLL.

+0

Это исправление с декабря 2010 года. Когда я задал вопрос (давным-давно), я использовал гораздо более современную версию Visual Studio, поэтому я думаю, что это не связано, к сожалению. – julealgon

3

Немного связанный, google привел меня сюда для очень похожей проблемы. Отладка t4-шаблона, когда генерируется исключение, заставляет T4VSHostProcess.exe блокировать все связанные DLL-файлы в шаблоне. Исправлена ​​проблема с перезапуском visual studio, но я смог просто использовать sysinternals process explorer и вручную убить процесс T4VSHostProcess.exe, чтобы избежать перезапуска визуальной студии.

Смежные вопросы