Unmanaged DLLs fail to load on ASP.NET server

空扰寡人 提交于 2019-11-26 18:30:21

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.

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.

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.

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

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.

yzorg

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.

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

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.

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.

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

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!