VS2013 опубликовать задачу веб-развертывания не удалось Файл используется
Я использую VS2013 Premium для публикации сайта на Windows Server 2012. Все файлы публикуются нормально, за исключением следующих: SqlServerTypes\x64\msvcr100.dll
SqlServerTypes\x64\SqlServerSpatial110.dll
SqlServerTypes\x86\msvcr100.dll
SqlServerTypes\x86\SqlServerSpatial110.dll
Я получаю такие ошибки для каждого из вышеперечисленных файлов, которые я пытался опубликовать: Не удалось выполнить задачу развертывания сети. (Файл "msvcr100.dll" используется. Подробнее читайте на странице: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_FILE_IN_USE.)
Интерресто, эти файлы были опубликованы в первый раз (когда их не было на сервере), то они больше не перезаписываются. Пробовал 2 разных веб-сервера. Я следил за гидом здесь: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
... Но ему удалось просто отключить сайт (VS размещает app_offline.htm), но публикация все еще не выполняется с той же ошибкой. Все остальные файлы публикуются отлично.
Есть идеи?
Ответы
Ответ 1
Вы можете отключить приложение во время публикации, которое, надеюсь, должно освободить блокировку файла и позволить вам обновить его.
Я писал об этом некоторое время назад. Описанная поддержка была отправлена внутри Azure SDK и Visual Studio Update. Я не помню точных релизов, но я могу узнать, если это необходимо. Любое обновление, связанное с этим сообщением в блоге, должно быть прекрасным.
Предпосылки:
- VS 2012 + VS update/VS 2013 + VS Update/VS2015
- MSDeploy v3
Примечание. Если вы публикуете с сервера CI, сервер CI также должен иметь обновленные обновления
Изменить профиль публикации
В VS при создании профиля веб-публикации настройки из диалогового окна хранятся в Properties\PublishProfiles\
виде файлов, которые заканчиваются на.pubxml. Примечание: есть файл .pubxml.user
, этот файл не следует изменять
Чтобы .pubxml
ваше приложение в файле .pubxml
добавьте следующее свойство.
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
Заметки
Требуется ASP.NET
Способ, которым это было реализовано на стороне MSDeploy, заключается в том, что файл app_offline.htm удаляется в корне сайта/приложения. Оттуда среда выполнения asp.net обнаружит это и отключит ваше приложение в автономном режиме. Из-за этого, если ваш сайт/приложение не поддерживает asp.net, эта функция не будет работать.
Случаи, когда он может не работать
Внедрение этого делает его таким, что приложение не может быть строго отключено до начала публикации. Сначала файл app_offline.htm отбрасывается, затем MSDeploy начинает публикацию файлов. Он не дожидался, пока ASP.NET обнаружит файл и фактически отключит его. Из-за этого вы можете столкнуться с ситуациями, когда вы все еще сталкиваетесь с блокировкой файлов. По умолчанию VS позволяет retrys, так что обычно приложение будет отключено во время одной из попыток, и все будет хорошо. В некоторых случаях для ASP.NET может потребоваться больше времени. Это немного сложнее.
Если вы добавите <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
и ваше приложение не будет достаточно скоро отключено, я предлагаю вам <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
приложение до начала публикации. Существует несколько способов сделать это удаленно, но это зависит от вашей настройки. Если у вас есть только доступ к MSDeploy, вы можете попробовать следующую последовательность:
- Используйте
msdeploy.exe
чтобы msdeploy.exe
ваш сайт, отменив app_offline.htm - Используйте
msdeploy.exe
для публикации своего приложения (убедитесь, что синхронизация не удаляет файл app_offline.htm_) - Подождите некоторое время
- Публикация сайта
- Используйте
msdeploy.exe
чтобы вывести приложение онлайн, удалив app_offline.htm
Я написал в блоге, как вы можете это сделать на http://sedodream.com/2012/01/08/howtotakeyourwebappofflineduringpublishing.aspx. Единственное, чего не хватает в этом сообщении в блоге, - это отсрочка ожидания того, что сайт фактически будет отключен. Вы также можете создать скрипт, который просто вызывает msdeploy.exe
непосредственно, вместо того, чтобы интегрировать его в процесс сборки/публикации проекта.
Ответ 2
Я нашел причину, почему решение в
http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
не работал для оригинального плаката, и у меня есть обходной путь.
Проблема с подходом EnableMSDeployAppOffline заключается в том, что он перерабатывает только домен приложения, в котором размещается приложение. Он не перезапускает рабочий процесс пула приложений (w3wp.exe), в котором находится домен приложения.
Снос и воссоздание домена приложения не повлияет на рассматриваемые dll Sql Server Spatial. Эти библиотеки представляют собой неуправляемый код, который загружается вручную с помощью вызовов LoadLibray. Поэтому библиотеки находятся за пределами области приложения.
Для снятия блокировок файлов, которые накладывает на них процесс пула приложений, необходимо либо перезапустить пул приложений, либо вручную выгружать библиотеки из памяти.
Пакет nuget Microsoft.SqlServer.Types содержит класс, который используется для загрузки пространственных библиотек с именем SqlServerTypes.Utilities. Вы можете изменить метод LoadNativeAssemblies, чтобы выгружать неуправляемые библиотеки DLL при выгрузке домена приложения. С этой модификацией, когда msdeploy копирует app_offline.htm, домен приложения будет выгружен, а затем также выгружен управляемые библиотеки.
[DllImport("kernel32.dll", SetLastError = true)]
internal extern static bool FreeLibrary(IntPtr hModule);
private static IntPtr _msvcrPtr = IntPtr.Zero;
private static IntPtr _spatialPtr = IntPtr.Zero;
public static void LoadNativeAssemblies(string rootApplicationPath)
{
if (_msvcrPtr != IntPtr.Zero || _spatialPtr != IntPtr.Zero)
throw new Exception("LoadNativeAssemblies already called.");
var nativeBinaryPath = IntPtr.Size > 4
? Path.Combine(rootApplicationPath, @"SqlServerTypes\x64\")
: Path.Combine(rootApplicationPath, @"SqlServerTypes\x86\");
_msvcrPtr = LoadNativeAssembly(nativeBinaryPath, "msvcr100.dll");
_spatialPtr = LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial110.dll");
AppDomain.CurrentDomain.DomainUnload += (sender, e) =>
{
if (_msvcrPtr != IntPtr.Zero)
{
FreeLibrary(_msvcrPtr);
_msvcrPtr = IntPtr.Zero;
}
if (_spatialPtr != IntPtr.Zero)
{
FreeLibrary(_spatialPtr);
_spatialPtr = IntPtr.Zero;
}
};
}
При таком подходе есть одна оговорка. Предполагается, что ваше приложение - единственное, которое выполняется в рабочем процессе, использующем пространственные библиотеки DLL. Поскольку пулы приложений могут содержать несколько приложений, блокировки файлов не будут сняты, если другое приложение также загрузило их. Это предотвратит работу вашего развертывания с той же ошибкой блокировки файлов.
Ответ 3
Известны проблемы с IIS и файловыми замками (почему они еще не решены, но я не знаю).
Вопрос, который я хочу задать, - это если вам даже нужно повторно развернуть эти файлы?
Я узнаю имена файлов и назову их системными файлами, которые должны либо присутствовать на сервере, либо просто не нуждаться в повторном развертывании.
Я не очень опытен, когда дело доходит до IIS, но я столкнулся с этой проблемой раньше, и несколько моих более опытных сотрудников сказали мне, что это так, как я сказал, известную проблему IIS, и я считаю, что ответ на ваш вопрос:
- Избегайте развертывания ненужных файлов.
- попробуй еще раз
- Сбросить сайт
- попробуй еще раз
- IISReset
Ответ 4
Я думаю, что было бы проще всего сделать эти DLL как CopyLocal как истинные. Я предполагаю, что эти dll вытащили из папки программных файлов. Попытайтесь пометить их как copylocal true и выполните развертывание. Попробуйте остановить локальный процесс IIS на вашем локальном компьютере.
Ответ 5
Следите за тем, чтобы у вас не было одной из тех запутанных приложений облачного резервного копирования, которые занимаются блокировками файлов, а также у вас нет вещей, открытых в проводнике или в инструменте проверки DLL.
Я думаю, что это смешно, что MS не делает лучшего положения для этой проблемы. Я нахожу, что 9 раз из 10 мое развертывание работает очень хорошо, но затем, поскольку наш трафик увеличивается, что может стать 1 в 10 раз.
Я собираюсь решить проблему:
- два приложения
MySite.A
и MySite.B
, где только один работает одновременно. - Я всегда разворачиваюсь на бездействующий сайт.
- Если во время развертывания возникнет проблема, он не заставит весь сайт опуститься.
- Если после развертывания возникает серьезная проблема, вы можете легко вернуться назад.
Не совсем уверен, как я это реализую, но я думаю, что это то, что мне нужно делать.