【问题标题】:IIS Shadow Copied DLL accessing dependency DLLs from bin locationIIS 影子复制 DLL 从 bin 位置访问依赖项 DLL
【发布时间】:2021-11-19 03:10:32
【问题描述】:

我正在尝试在 IIS 中使用 EFCore 3.1.16 解决 ASP.Net Framework 4.8 站点的问题。 Microsoft.Data.SqlClient 在 SNI.dll 上有一个进程锁定,这会导致 IIS 中的 xcopy 部署出现问题。

我尝试了将 SNI.dll 复制到与 Microsoft.Data.SqlClient 相同的卷影副本位置的策略,因此它不必尝试访问 bin 文件夹中的 DLL,如https://github.com/lscorcia/sqlclient.snishadowcopy 中所述。

// Look for the main Microsoft.Data.SqlClient assembly in the 
// shadow copy path
var sqlClientShadowAssembly = Directory.GetFiles(
currentShadowPath, "Microsoft.Data.SqlClient.dll",
SearchOption.AllDirectories).FirstOrDefault();

// Extract the directory information from the shadow assembly path
var sqlClientShadowPath = 
Path.GetDirectoryName(sqlClientShadowAssembly);

// Find out the process bitness and choose the appropriate native 
// assembly
var moduleName = Environment.Is64BitProcess ? "x86\\SNI.dll"
        : "x64\\SNI.dll";
// Compute the source and target paths for the native assembly
var sourceFile = Path.Combine(currentPrivatePath, moduleName);
var targetFile = Path.Combine(sqlClientShadowPath, "SNI.dll");
File.Copy(sourceFile, targetFile);

但是,它仍然会首先尝试访问 bin 位置,而不是位于同一文件夹位置的 sni.dll。

我已通过删除 DLL 并确认引发 FileNotFound 异常来检查影子位置中的 Microsoft.Data.SqlClient 是否正确使用。我还尝试直接复制到同一个文件夹并复制到 x64阴影位置中的子文件夹。

【问题讨论】:

  • 升级到 .NET 6 然后就可以使用真正的卷影副本docs.microsoft.com/en-us/aspnet/core/release-notes/…
  • 你用的是什么应用程序?如果是 asp.net 应用程序,IIS 不会在进程运行时阻止 dll 文件。如果是asp.net核心应用,需要升级到.net 6。

标签: asp.net iis xcopy ef-core-3.1 shadow-copy


【解决方案1】:

就我而言,仅当我的 IIS 应用程序位于 UNC 路径(例如“\\myserver\myshare\myapplication”)上时才会发生错误。这是一种适用于我的方案的解决方法。

使用 P/Invoke 到 SetDllDirectory:

[DllImport(@"kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName);

(另见this MSDN article about DLL load order

然后,在我的 Global.asax.cs Application_Start 方法的早期(在任何数据库调用之前),这样调用它:

SetDllDirectory(Server.MapPath(@"~/bin"))

之后,一切都按预期进行。


我仍然认为这是一种黑客/解决方法,但至少,它现在在我的场景中工作。

据我了解,您可以多次调用SetDllDirectory添加其他目录(即不覆盖现有目录)。

因此,如果阅读本文的人可能有其他程序集引用“x86”或“x64”文件夹中的本机 DLL,则可能会执行以下操作:

var bitness = Environment.Is64BitProcess ? @"x64" : @"x86";
SetDllDirectory(Server.MapPath($@"~/bin/{bitness}"));

我还尝试从本地路径(如“C:\Inetpub\wwwroot”)提供我的测试应用程序,在这里,即使没有调用SetDllDirectory,错误不会发生.

我仍然不确定为什么错误只发生在 UNC 路径,而不是本地路径,因为我预计影子复制的托管程序集也会使 DllImports 失败。


(上面我也发过in this GitHub issue

【讨论】:

    猜你喜欢
    • 2014-08-30
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2018-11-02
    • 2010-11-05
    • 2021-11-19
    • 2010-12-13
    相关资源
    最近更新 更多