我已经找到了解决方案为什么在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 dlls。这些dll是通过interop LoadLibray调用手动加载的非托管代码。因此,这些dll位于应用程序域范围之外。
为了释放文件锁定,您需要回收应用程序池或手动从内存中卸载dll。
Microsoft.SqlServer.Types nuget包提供了一个类,用于加载空间dlls,名为SqlServerTypes.Utilities。您可以修改LoadNativeAssemblies方法以在卸载应用程序域时卸载非托管dll。通过这个修改,当msdeploy复制app_offline.htm时,应用程序域将卸载,然后也会卸载托管dll。
[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运行的工作进程中唯一运行的。由于应用程序池可以托管多个应用程序,如果另一个应用程序也加载了它们,则文件锁定将不会释放。这将导致您的部署出现相同的文件锁定错误。