非托管 DLL 无法在 ASP.NET 服务器上加载

发布于 2024-07-10 23:04:33 字数 894 浏览 4 评论 0原文

这个问题涉及一个 ASP.NET 网站,最初是在 VS 2005 中开发的,现在是在 VS 2008 中开发的。

该网站使用两个非托管外部 DLL,它们不是 .NET,我没有编译它们的源代码,必须将它们用作是。

该网站在 Visual Studio 中运行良好,可以正确定位和访问这些外部 DLL。 但是,当网站发布在网络服务器(运行 IIS6 和 ASP.NET 2.0)而不是开发 PC 上时,它无法定位和访问这些外部 DLL,并且出现以下错误:

无法加载 DLL 'XYZ.DLL'。 dll': 找不到指定的模块。 (HRESULT 异常:0x8007007E)

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

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

我已尝试以下操作:

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

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

This question relates to an ASP.NET website, originally developed in VS 2005 and now in VS 2008.

This website uses two unmanaged external DLLs which are not .NET and I do not have the source code to compile them and have to use them as is.

This website runs fine from within Visual Studio, locating and accessing these external DLLs correctly. However, when the website is published on a webserver (runnning IIS6 and ASP.NET 2.0) rather than the development PC it cannot locate and access these external DLLs, and I get the following error:

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

The external DLLs are located in the bin directory of the website, along with the managed DLLs that wrap them and all the other DLLs for the website.

Searching this problem reveals that many other people seem to have the same problem accessing external non.NET DLLs from ASP.NET websites, but I haven't found a solution that works.

I have tried the following:

  • Running DEPENDS to check the dependencies to establish that the first three
    are in System32 directory in the path, the last is in the .NET 2
    framework.
  • I put the two DLLs and their dependencies in
    System32 and rebooted the server, but website still
    couldn't load these external DLLs.
  • Gave full rights to ASPNET, IIS_WPG and IUSR (for that server) to
    the website bin directory and rebooted, but website still couldn't
    load these external DLLs.
  • Added the external DLLs as existing items to the projects and set
    their "Copy to Output" property to "Copy Always", and website
    still can't find the DLLs.
  • Also set their "Build Action" property to "Embedded resource" and
    website still can't find the DLLs.

Any assistance with this problem would be greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

情深缘浅 2024-07-17 23:04:33

发生这种情况是因为托管 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 地狱。

This happens because the managed dlls get shadow copied to a temporary location under the .NET Framework directory. See http://msdn.microsoft.com/en-us/library/ms366723.aspx for details.

Unfortunately, the unmanaged dlls do NOT get copied and the ASP.NET process won't be able to find them when it needs to load them.

One easy solution is to put the unmanaged dlls in a directory that is in the system path (type "path" at the command line to see the path on your machine) so that they can be found by the ASP.NET process. The System32 directory is always in the path, so putting the unmanaged dlls there always works, but I would recommend adding some other folder to the path and then adding the dlls there to prevent polluting the System32 directory. One big drawback to this method is you have to rename the unmanaged dlls for every version of your application and you can quickly have your own dll hell.

毅然前行 2024-07-17 23:04:33

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

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

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

As an alternate to putting the dll in a folder that is already in the path (like system32) you can change the path value in your process by using the following code

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

Then when LoadLibrary tries to find the unmanaged DLL it will also scan searchPath. This may be preferable to making a mess in System32 or other folders.

酒与心事 2024-07-17 23:04:33

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

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

Try putting the dlls in the \System32\Inetsrv directory. This is the working directory for IIS on Windows Server.

If this doesn't work try putting the dlls in the System32 directory and the dependency files in the Inetsrv directory.

邮友 2024-07-17 23:04:33

添加到马特的答案中,这就是最终对我的64位服务器2003 / IIS 6起作用的方法:

  1. 确保您的dll / asp.net是相同的版本(32 / 64位)
  2. 将非托管dll放入inetsrv目录中(请注意在 64 位 Windows 中,这是在 syswow64 下,即使创建了 sys32/inetsrv 目录)
  3. 将托管 dll 保留在 /bin 中
  4. 确保两组 dll 都具有读取/执行权限

Adding to Matt's answer, this is what finally worked for me for 64-bit server 2003 / IIS 6:

  1. make sure your dlls / asp.net are the same version (32 / 64 bit)
  2. Put the unmanaged dlls in inetsrv dir (note that in 64 bit windows, this is under syswow64, even though the sys32/inetsrv directory is created)
  3. Leave the managed dlls in /bin
  4. Make sure both sets of dll's have read/execute permissions
愛上了 2024-07-17 23:04:33

使用 FileMonProcMon 并过滤有问题的 DLL 的名称。 这将向您显示在搜索 DLL 时扫描哪些目录,以及您可能遇到的任何权限问题。

Take a look with FileMon or ProcMon and filter on the names of the troublesome DLLs. This will show you what directories are scanned in search of the DLLs, and any permission issues you might have.

郁金香雨 2024-07-17 23:04:33

另一种选择是将本机 DLL 作为资源嵌入到托管 DLL 中。 这在 ASP.NET 中更为复杂,因为它需要在运行时写入临时文件夹。 该技术在另一个 SO 答案中进行了解释

Another option is embedding the native DLL as a resource in the managed DLL. This is more complicated in ASP.NET, as it requires writing to temporary folder at runtime. The technique is explained in another SO answer.

眼眸里的那抹悲凉 2024-07-17 23:04:33

Always worth checking the path variable in your environment settings too.

只涨不跌 2024-07-17 23:04:33

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

I have come across the same issue. And I tried all above options, copying to system32, inetpub, setting path environment, etc nothing worked.
This issue is finally resolved by copying unmanaged dll to the bin directory of web application or web service.

如果没结果 2024-07-17 23:04:33

经过一整天的努力,我终于找到了适合我的解决方案。 这只是一个测试,但方法是有效的。

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();
                  }
                }
          }
        }
    }
}

Аfter struggling all day over this problem and finally I found a solution which suits me. It's just a test, but the method is working.

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();
                  }
                }
          }
        }
    }
}
落叶缤纷 2024-07-17 23:04:33

在您将 XYZ.dll 部署到的位置直接运行 DEPENDS。 如果这没有显示任何丢失的内容,请使用平台 SDK 中的 fuslogvw 工具来跟踪加载程序错误。 此外,事件日志有时包含有关加载 DLL 失败的信息。

Run DEPENDS on XYZ.dll directly, in the location that you have deployed it to. If that doesn't reveal anything missing, use the fuslogvw tool in the platform SDK to trace loader errors. Also, the event logs sometimes contain information about failures to load DLLs.

鹿港巷口少年归 2024-07-17 23:04:33

在 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);

On Application_start use this:
(customise /bin/x64 and bin/dll/x64 folders as needed)

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);
深居我梦 2024-07-17 23:04:33

尝试将 DLL 放入 Windows/SysWOW64 文件夹中。 这是唯一对我有用的事情。

Try putting the DLL in the Windows/SysWOW64 folder. It was the only thing that worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文