2008-12-05 75 views
60

这个问题涉及到一个ASP.NET网站,最初在2005年VS现在在VS 2008托管DLL不能ASP.NET服务器上加载

本网站使用了哪些不是.NET 2个非托管的外部DLL开发而我没有源代码来编译它们,并且必须按原样使用它们。

本网站在Visual Studio中正常运行,正确定位和访问这些外部DLL。但是,当网站被发布在网络服务器(捉迷藏IIS6和ASP.NET 2.0)而不是开发PC时,无法找到和访问这些外部DLL,我得到以下错误:

Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

的外部DLL位于网站的bin目录中,以及包装它们的托管DLL以及网站的所有其他DLL。

搜索这个问题揭示了许多其他人似乎有访问来自ASP.NET网站的外部非.NET DLL的相同问题,但我还没有找到可行的解决方案。

我曾尝试以下:

  • 运行一方面依赖于检查依赖建立的前三个 在System32目录的路径,最后是在.NET 2 框架。
  • 我把这两个DLL及其依赖关系放在 System32中,并重新启动服务器,但网站仍然无法加载这些外部DLL。
  • 将ASPNET,IIS_WPG和IUSR(对于该服务器)的权限设置为 网站bin目录并重新启动,但网站仍不能 加载这些外部DLL。
  • 将外部DLL作为现有项目添加到项目中,并将其“复制到输出”属性的 设置为“始终复制”,并且网站 仍无法找到这些DLL。
  • 还将其“Build Action”属性设置为“嵌入式资源”,并且 网站仍然无法找到该DLL。

对此问题的任何帮助将不胜感激!

回答

21

尝试将dll放在\ System32 \ Inetsrv目录中。这是Windows Server上IIS的工作目录。

如果这不起作用,请尝试将dll放在System32目录和Inetsrv目录中的依赖项文件中。

+3

下面是一个答案,不需要污染system32文件夹:http://stackoverflow.com/a/4598747/92756 – 2013-07-01 13:17:42

+4

相反,您可以通过添加<在web.config上托管环境shadowCopyBinAsmblies =“false”/>,前提是您不在实时应用程序中修改二进制文件。 – Amit 2015-06-29 22:47:51

+0

因为我忘记了它,我把DLL的一个副本放到了System32中,导致我烧了,然后我的Microsoft.Azure.Documents.ServiceInterop.dll的错误版本被加载,导致我的项目导致奇怪的本地queryRanges尝试连接到数据库时出现[0] .isMinInclusive错误。我的修复最终确保我的本地IIS DefaultAppPool身份是我的本地用户。另请参阅:https://github.com/Azure/azure-documentdb-dotnet/issues/267 – Zachstronaut 2017-06-12 22:03:25

1

直接在XYZ.dll上运行DEPENDS,并将其部署到的位置。如果没有发现任何缺失,请使用平台SDK中的fuslogvw工具来跟踪加载器错误。此外,事件日志有时包含有关加载DLL失败的信息。

+0

你能链接到我能得到的地方吗? – 2008-12-05 20:42:03

+0

这里是:http://www.dependencywalker.com/ – Werg38 2008-12-06 17:33:31

6

看一下FileMonProcMon并过滤出有问题的DLL的名称。这将向您显示搜索DLL的扫描目录以及您可能遇到的任何许可问题。

+1

ProcMon在计算依赖关系以及某个DLL不会加载的情况下非常有用。 – Oliver 2016-05-26 11:43:20

1

在您的环境设置中总是值得使用checking the path变量。

+0

链接去哪里 – Ristogod 2012-11-13 19:54:44

+7

@Ristogod:答案是四岁,你低调我,因为我没有跟踪确保链接是活跃的?艰难的人群。 – annakata 2012-11-14 20:58:06

10

添加到马特的答案,这是什么终于为我工作的64位服务器2003/IIS 6:

  1. 确保您的dll/asp.net是相同的版本(32/64位)
  2. 把托管DLL在INETSRV目录(注意,在64位的Windows,这是根据SysWow64资料,即使创建的sys32/inetsrv目录)
  3. 离开管理的dll文件位于/ bin
  4. 确保两套的dll有读取/执行权限
39

发生这种情况是因为托管的dll将阴影复制到.NET Framework目录下的临时位置。详情请参阅http://msdn.microsoft.com/en-us/library/ms366723.aspx

不幸的是,非托管dll不会被复制,并且ASP.NET进程无法在需要加载它们时找到它们。

一个简单的解决方案是将非托管dll放入系统路径中的一个目录(在命令行键入“path”以查看计算机上的路径),以便可以通过ASP.NET找到它们处理。 System32目录中的始终为,因此将非托管dll始终可用,但我建议将其他文件夹添加到路径中,然后在其中添加dll以防止污染System32目录。这种方法的一大缺点是你必须重命名你的应用程序的每个版本的非托管dll,你可以很快拥有你自己的dll地狱。

35

作为替代,以把DLL,它已经在该路径(像SYSTEM32),则可以通过使用下面的代码

System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath) 

然后,当调用LoadLibrary试图在过程改变路径值的文件夹中找到它将扫描searchPath的非托管DLL。这可能比在System32或其他文件夹中弄得乱七八糟。

1

我碰到过同样的问题。我尝试了以上所有选项,复制到system32,inetpub,设置路径环境等,没有任何工作。 通过将非托管dll复制到Web应用程序或Web服务的bin目录,最终解决了此问题。

1

一整天在这个问题上挣扎,终于找到了适合我的解决方案。这只是一个测试,但方法正在工作。

namespace TestDetNet 
{ 
    static class NativeMethods 
    { 
     [DllImport("kernel32.dll")] 
     public static extern IntPtr LoadLibrary(string dllToLoad); 

     [DllImport("kernel32.dll")] 
     public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 


     [DllImport("kernel32.dll")] 
     public static extern bool FreeLibrary(IntPtr hModule); 
    } 

    public partial class _Default : System.Web.UI.Page 
    { 
     [UnmanagedFunctionPointer(CallingConvention.StdCall)] 
     private delegate int GetRandom(); 

     protected System.Web.UI.WebControls.Label Label1; 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      Label1.Text = "Hell'ou"; 
      Label1.Font.Italic = true; 
     } 

     protected void Button1_Click(object sender, EventArgs e) 
     { 
      if (File.Exists(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll")) { 
       IntPtr pDll = NativeMethods.LoadLibrary(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll"); 
       if (pDll == IntPtr.Zero) { Label1.Text = "pDll is zero"; } 
       else 
       { 
        IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "GetRandom"); 
        if (pAddressOfFunctionToCall == IntPtr.Zero) { Label1.Text += "IntPtr is zero"; } 
        else 
        { 
        GetRandom _getRandom = (GetRandom)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(GetRandom)); 

        int theResult = _getRandom(); 

        bool result = NativeMethods.FreeLibrary(pDll); 
        Label1.Text = theResult.ToString(); 
        } 
       } 
      } 
     } 
    } 
}