代码之家  ›  专栏  ›  技术社区  ›  Werg38

ASP上无法加载非托管DLL。服务器

  •  71
  • Werg38  · 技术社区  · 17 年前

    这个问题与ASP有关。NET网站,最初是在VS 2005中开发的,现在是在VS 2008中开发的。

    此网站使用两个非托管的外部DLL,它们不是。NET,我没有编译它们的源代码,只能按原样使用它们。

    此网站在Visual Studio中运行良好,可以正确定位和访问这些外部DLL。但是,当网站在Web服务器(运行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与包装它们的托管DLL以及网站的所有其他DLL一起位于网站的bin目录中。

    搜索此问题后发现,许多其他人在访问外部非时似乎也有同样的问题。NET DLL从ASP。NET网站,但我还没有找到一个有效的解决方案。

    我尝试了以下方法:

    • 运行DEPENDS检查依赖关系,以确定前三个 在System32目录的路径中,最后一个在。净值2 框架。
    • 我将这两个DLL及其依赖项放入 System32并重新启动了服务器,但网站仍然 无法加载这些外部DLL。
    • 授予ASPNET、IIS_WPG和IUSR(用于该服务器)的全部权限 网站bin目录并重新启动,但网站仍然无法 加载这些外部DLL。
    • 将外部DLL作为现有项添加到项目中并设置 他们的“复制到输出”属性为“始终复制”,以及网站 仍然找不到DLL。
    • 还将其“构建操作”属性设置为“嵌入式资源”,并 网站仍然找不到DLL。

    非常感谢您对这个问题的任何帮助!

    12 回复  |  直到 17 年前
        1
  •  49
  •   onedozenbagels    17 年前

    这是因为托管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地狱。

        2
  •  42
  •   Matt Woodard    13 年前

    作为将dll放入路径中已有的文件夹(如system32)的替代方法,您可以使用以下代码更改进程中的路径值

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

    然后,当LoadLibrary尝试查找非托管DLL时,它也会扫描searchPath。这可能比在System32或其他文件夹中搞砸要好。

        3
  •  22
  •   Matt    17 年前

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

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

        4
  •  12
  •   a_horse_with_no_name    10 年前

    除了Matt的回答,这就是我最终在64位服务器2003/IIS 6上使用的方法:

    1. 确保你的dlls/asp.net是相同的版本(32/64位)
    2. 将非托管dll放在inetsrv目录中(注意,在64位窗口中,即使创建了sys32/inetsrv目录,它也在syswow64下)
    3. 将托管dll保留在/bin中
    4. 确保两组dll都具有读取/执行权限
        5
  •  6
  •   Arnout    17 年前

    看看 FileMon 或 ProcMon 并过滤出有问题的DLL的名称。这将显示在搜索DLL时扫描了哪些目录,以及您可能遇到的任何权限问题。

        6
  •  4
  •   Community Mohan Dere    9 年前

    另一种选择是将本机DLL作为资源嵌入托管DLL中。这在ASP。NET,因为它需要在运行时写入临时文件夹。 The technique is explained in another SO answer .

        7
  •  2
  •   annakata    17 年前

    永远值得 checking the path 环境设置中也有变量。

        8
  •  2
  •   Ram Chavakula    11 年前

    我也遇到过同样的问题。我尝试了上述所有选项,复制到system32、inetpub、设置路径环境等,但都没有效果。 通过将非托管dll复制到web应用程序或web服务的bin目录,此问题最终得以解决。

        9
  •  2
  •   Mad Dog    10 年前

    在为这个问题挣扎了一整天之后,我终于找到了一个适合我的解决方案。这只是一个测试,但这种方法正在奏效。

    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();
                      }
                    }
              }
            }
        }
    }
    
        10
  •  1
  •   jlew    17 年前

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

        11
  •  0
  •   Ers    8 年前

    在Application_start上使用以下命令: (根据需要自定义/bin/x64和bin/dll/x64文件夹)

    String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH")
                    ,";"
                    , System.Web.Hosting.HostingEnvironment.MapPath("~/bin/x64")
                    ,";"
                    , System.Web.Hosting.HostingEnvironment.MapPath("~/bin/dll/x64")
                    ,";"
                    );
                System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);