我正在使用VS2013 Premium将站点发布到Windows Server 2012。 所有文件发布正常,除了这些: SqlServerTypes \ 64 \ msvcr100.dll
SqlServerTypes \ 64 \ SqlServerSpatial110.dll
SqlServerTypes \ 86 \ msvcr100.dll
SqlServerTypes \ 86 \ SqlServerSpatial110.dll
我试图发布上述每个文件都会出现这种错误: Web部署任务失败。 (文件' msvcr100.dll'正在使用中。请访问:http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_FILE_IN_USE了解详情。)
有趣的是,这些文件是第一次发布(当它们不在服务器上时),然后它们不再被覆盖。试过2个不同的Web服务器。 我在这里遵循了指南: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx...但它只是设法使网站脱机(VS放置app_offline.htm)但发布仍然失败并出现相同的错误。 所有其他文件发布完美。
有什么想法吗?
答案 0 :(得分:25)
您可以在发布期间使应用程序脱机,希望释放文件上的锁定并允许您更新它。
我blogged about this一会儿回来。概述的支持是在Azure SDK和Visual Studio Update中提供的。我不记得确切的版本,但我可以找出是否需要。在该博客文章附近/之后的任何更新都应该没问题。
注意:如果您要从CI服务器发布,CI服务器也需要上面的更新
在VS中创建Web发布配置文件时,对话框中的设置存储在Properties\PublishProfiles\
中,作为以.pubxml结尾的文件。 注意:还有一个.pubxml.user
文件,该文件不应修改
要在.pubxml
文件中使您的应用离线,请添加以下属性。
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
在MSDeploy方面实现此方法的方法是将app_offline.htm文件放在网站/应用程序的根目录中。从那里,asp.net运行时将检测到并使您的应用程序脱机。因此,如果您的网站/应用程序没有启用asp.net,则此功能将无效。
这样做的实现使得应用程序在发布开始之前可能不会严格脱机。首先删除app_offline.htm文件,然后MSDeploy将开始发布文件。它不等待ASP.NET检测文件并实际使其脱机。因此,您可能遇到仍然遇到文件锁的情况。默认情况下,VS启用重试,因此通常应用程序将在其中一个重试期间脱机,一切都很好。在某些情况下,ASP.NET可能需要更长时间才能响应。这有点棘手。
如果你添加<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
并且你的应用程序很快没有下线,那么我建议您在发布开始之前使应用程序脱机。有几种方法可以远程执行此操作,但这取决于您的设置。如果您只有MSDeploy访问权限,则可以尝试以下顺序:
msdeploy.exe
使您的网站脱机
msdeploy.exe
发布您的应用(_确保同步不会删除app_offline.htm文件_)msdeploy.exe
删除app_offline.htm 我已在博客上发表了如何在http://sedodream.com/2012/01/08/howtotakeyourwebappofflineduringpublishing.aspx处执行此操作的内容。该博客文章中唯一缺少的是延迟等待网站实际脱机。您还可以创建一个直接调用msdeploy.exe
的脚本,而不是将其集成到项目构建/发布过程中。
答案 1 :(得分:6)
我找到了解决方案的原因 http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx 不适用于原始海报,我有一个解决方法。
EnableMSDeployAppOffline方法的问题在于它只回收托管应用程序的应用程序域。它不会回收应用程序域所在的应用程序池工作进程(w3wp.exe)。
拆除并重新创建应用程序域不会影响有问题的Sql Server Spatial dll。这些dll是非托管代码,通过interop LoadLibray调用手动加载。因此,dll不在app域的范围之内。
为了释放应用程序池进程对其进行的文件锁定,您需要回收应用程序池,或者手动从内存中卸载dll。
Microsoft.SqlServer.Types nuget包附带一个类,用于加载名为SqlServerTypes.Utilities的Spatial dll。您可以修改LoadNativeAssemblies方法以在卸载应用程序域时卸载非托管dll。通过此修改,当msdeploy复制app_offline.htm时,app域将卸载然后卸载托管dll。
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;
}
};
}
这种方法有一点需要注意。它假定您的应用程序是在使用Spatial dll的工作进程中运行的唯一应用程序。由于应用程序池可以托管多个应用程序,因此如果另一个应用程序也加载了它们,则不会释放文件锁这将阻止您的部署使用相同的文件锁定错误。
答案 2 :(得分:1)
IIS和文件锁存在已知问题(为什么它们还没有解决但我不知道)。
我想问的问题是,你是否需要重新部署这些文件?
我识别文件名并将它们记为系统文件,这些文件应该已经存在于服务器上,或者根本不需要重新部署。
我对IIS不是很有经验,但我之前遇到过这个问题,我的一些经验丰富的同事告诉我,这就像我说的一个已知的IIS问题,我相信答案你的问题是:
答案 3 :(得分:1)
我认为最简单的方法是将这些dll设为CopyLocal为true。我假设这些dll是从程序文件文件夹中提取出来的。尝试将它们标记为copylocal true并进行部署。尝试停止在本地计算机上运行的任何IIS本地进程。
答案 4 :(得分:0)
请注意,您没有运行带有文件锁定的新型云备份服务之一 - 而且您还没有在资源管理器或DLL检查工具中打开任何内容。
我认为MS没有为这个问题做出更好的规定,这有点荒谬。我发现9次中有10次我的部署运行得很好,但随后我们的流量增加了10次就会变成1次。
我将用以下方法解决问题:
MySite.A
和MySite.B
,其中一次只有一个正在运行。 我不太确定我是如何实现它的,但我认为这是我需要做的。