非托管dll在ASP上加载失败。网络服务器

时间:2022-09-01 09:29:08

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

这个问题与ASP有关。NET网站,最初在VS 2005年开发,现在在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.

本网站使用两个非. net的非托管外部dll,我没有编译它们的源代码,必须按原样使用它们。

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:

这个网站在Visual Studio中运行良好,可以正确地定位和访问这些外部dll。然而,当网站发布在web服务器上时(运行IIS6和ASP)。它不能定位和访问这些外部dll,而不是开发PC,我得到以下错误:

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

无法加载DLL 'XYZ。找不到指定的模块。(从HRESULT例外:0 x8007007e)

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.

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

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.

搜索这个问题可以发现,许多其他人似乎也有同样的问题。净dll从ASP。NET网站,但是我还没有找到一个有效的解决方案。

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.
  • 运行依赖于检查依赖项以确定前三个在路径中的System32目录中,最后一个在。net 2框架中。
  • I put the two DLLs and their dependencies in System32 and rebooted the server, but website still couldn't load these external DLLs.
  • 我将两个dll及其依赖项放在System32中并重新启动服务器,但是网站仍然无法加载这些外部dll。
  • 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.
  • 将ASPNET、IIS_WPG和IUSR(用于该服务器)的全部权限授予网站bin目录并重新启动,但网站仍然无法加载这些外部dll。
  • 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.
  • 将外部dll作为现有项目添加到项目中,并将其“Copy to Output”属性设置为“Copy Always”,网站仍然无法找到dll。
  • Also set their "Build Action" property to "Embedded resource" and website still can't find the DLLs.
  • 还将其“构建动作”属性设置为“嵌入式资源”,网站仍然无法找到dll。

Any assistance with this problem would be greatly appreciated!

如有任何帮助,我们将不胜感激!

10 个解决方案

#1


20  

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

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

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

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

#2


41  

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.

这是因为托管dll将影子复制到. net框架目录下的临时位置。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms366723.aspx。

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.

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

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.

一个简单的解决方案是将非托管dll放在系统路径的目录中(在命令行输入“path”以查看计算机上的路径),以便ASP能够找到它们。净的过程。System32目录总是在路径中,所以将未管理的dll放在那里总是可行的,但是我建议在path中添加一些其他的文件夹,然后在那里添加dll,以防止污染System32目录。这个方法的一个很大的缺点是您必须为每个应用程序版本重命名非托管dll,并且您可以快速拥有自己的dll hell。

#3


36  

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

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

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.

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

#4


10  

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

添加到Matt的回答中,这是我最终为64位服务器2003 / iis6所做的工作:

  1. make sure your dlls / asp.net are the same version (32 / 64 bit)
  2. 确保你的dll / asp.net是相同的版本(32 / 64位)
  3. 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)
  4. 将非托管dll放入inetsrv dir(注意,在64位窗口中,这是在syswow64下,即使创建了sys32/inetsrv目录)
  5. Leave the managed dlls in /bin
  6. 将托管dll留在/bin中
  7. Make sure both sets of dll's have read/execute permissions
  8. 确保两组dll都具有读/执行权限。

#5


6  

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.

查看FileMon或ProcMon,并过滤恼人的dll的名称。这将向您显示在搜索dll时要扫描哪些目录,以及可能存在的任何权限问题。

#6


3  

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.

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

#7


1  

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.

运行取决于XYZ。直接在你部署它的位置。如果没有发现任何遗漏,请使用平台SDK中的fuslogvw工具来跟踪加载程序错误。此外,事件日志有时包含关于加载dll失败的信息。

#8


1  

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

始终值得检查环境设置中的path变量。

#9


1  

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.

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

#10


1  

А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.

Аfter整天挣扎在这个问题,最后我找到了一个适合我的解决方案。这只是一个测试,但是方法是有效的。

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

#1


20  

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

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

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

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

#2


41  

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.

这是因为托管dll将影子复制到. net框架目录下的临时位置。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms366723.aspx。

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.

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

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.

一个简单的解决方案是将非托管dll放在系统路径的目录中(在命令行输入“path”以查看计算机上的路径),以便ASP能够找到它们。净的过程。System32目录总是在路径中,所以将未管理的dll放在那里总是可行的,但是我建议在path中添加一些其他的文件夹,然后在那里添加dll,以防止污染System32目录。这个方法的一个很大的缺点是您必须为每个应用程序版本重命名非托管dll,并且您可以快速拥有自己的dll hell。

#3


36  

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

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

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.

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

#4


10  

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

添加到Matt的回答中,这是我最终为64位服务器2003 / iis6所做的工作:

  1. make sure your dlls / asp.net are the same version (32 / 64 bit)
  2. 确保你的dll / asp.net是相同的版本(32 / 64位)
  3. 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)
  4. 将非托管dll放入inetsrv dir(注意,在64位窗口中,这是在syswow64下,即使创建了sys32/inetsrv目录)
  5. Leave the managed dlls in /bin
  6. 将托管dll留在/bin中
  7. Make sure both sets of dll's have read/execute permissions
  8. 确保两组dll都具有读/执行权限。

#5


6  

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.

查看FileMon或ProcMon,并过滤恼人的dll的名称。这将向您显示在搜索dll时要扫描哪些目录,以及可能存在的任何权限问题。

#6


3  

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.

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

#7


1  

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.

运行取决于XYZ。直接在你部署它的位置。如果没有发现任何遗漏,请使用平台SDK中的fuslogvw工具来跟踪加载程序错误。此外,事件日志有时包含关于加载dll失败的信息。

#8


1  

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

始终值得检查环境设置中的path变量。

#9


1  

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.

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

#10


1  

А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.

Аfter整天挣扎在这个问题,最后我找到了一个适合我的解决方案。这只是一个测试,但是方法是有效的。

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