Pregunta

Esta pregunta se refiere a un sitio web ASP.NET, desarrollado originalmente en VS 2005 y ahora en VS 2008.

Este sitio web utiliza dos DLL externas no administradas que no son .NET y no tengo el código fuente para compilarlas y tengo que usarlas como están.

Este sitio web funciona bien desde Visual Studio, localizando y accediendo a estas DLL externas correctamente. Sin embargo, cuando el sitio web se publica en un servidor web (ejecutando IIS6 y ASP.NET 2.0) en lugar de la PC de desarrollo, no puede ubicar y acceder a estas DLL externas, y aparece el siguiente error:

No se puede cargar la DLL 'XYZ.dll': no ??se pudo encontrar el módulo especificado. (Excepción de HRESULT: 0x8007007E)

Las DLL externas se encuentran en el directorio bin del sitio web, junto con las DLL administradas que las envuelven y todas las demás DLL del sitio web.

La búsqueda de este problema revela que muchas otras personas parecen tener el mismo problema al acceder a archivos DLL externos que no son .NET desde sitios web ASP.NET, pero no he encontrado una solución que funcione.

He intentado lo siguiente:

  • Ejecutando DEPENDS para verificar las dependencias para establecer que los tres primeros están en el directorio System32 en la ruta, el último está en .NET 2 marco.
  • Puse las dos DLL y sus dependencias en System32 y reinició el servidor, pero el sitio web aún no se pudieron cargar estas DLL externas.
  • Dio todos los derechos a ASPNET, IIS_WPG e IUSR (para ese servidor) para el directorio bin del sitio web y se reinició, pero el sitio web aún no pudo cargar estas DLL externas.
  • Se agregaron las DLL externas como elementos existentes a los proyectos y se establecieron su " Copiar a salida " propiedad de "Copiar siempre" y sitio web todavía no puedo encontrar las DLL.
  • También configure su " Build Action " propiedad de " recurso incrustado " y el sitio web todavía no puede encontrar las DLL.

¡Cualquier ayuda con este problema sería muy apreciada!

¿Fue útil?

Solución

Intente colocar los archivos dlls en el directorio \ System32 \ Inetsrv. Este es el directorio de trabajo para IIS en Windows Server.

Si esto no funciona, intente poner los dlls en el directorio System32 y los archivos de dependencia en el directorio Inetsrv.

Otros consejos

Esto sucede porque los archivos DLL administrados se copian en una ubicación temporal en el directorio de .NET Framework. Consulte http://msdn.microsoft.com/en-us/library/ms366723. aspx para más detalles.

Desafortunadamente, los archivos DLL no administrados NO se copian y el proceso ASP.NET no podrá encontrarlos cuando necesite cargarlos.

Una solución fácil es colocar los archivos DLL no administrados en un directorio que se encuentra en la ruta del sistema (escriba " ruta " en la línea de comando para ver la ruta en su máquina) para que ASP.NET los pueda encontrar proceso. El directorio System32 está siempre en la ruta, por lo que colocar los dlls no administrados allí siempre funciona, pero recomendaría agregar alguna otra carpeta a la ruta y luego agregar los dlls allí para evitar contaminar el directorio System32. Un gran inconveniente de este método es que debe cambiar el nombre de los dlls no administrados para cada versión de su aplicación y puede tener rápidamente su propio dll hell.

Como alternativa a colocar el dll en una carpeta que ya está en la ruta (como system32), puede cambiar el valor de la ruta en su proceso utilizando el siguiente código

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

Luego, cuando LoadLibrary intenta encontrar la DLL no administrada, también escaneará searchPath. Esto puede ser preferible a hacer un desastre en System32 u otras carpetas.

Agregando a la respuesta de Matt, esto es lo que finalmente funcionó para mí para el servidor 2003 / IIS 6 de 64 bits:

  1. asegúrese de que sus dlls / asp.net sean de la misma versión (32/64 bits)
  2. Ponga los dlls no administrados en el directorio inetsrv (tenga en cuenta que en ventanas de 64 bits, esto está bajo syswow64, aunque se haya creado el directorio sys32 / inetsrv)
  3. Deja los dlls administrados en / bin
  4. Asegúrese de que ambos conjuntos de archivos dll tengan permisos de lectura / ejecución

Eche un vistazo con FileMon o ProcMon y filtre los nombres de las DLL problemáticas. Esto le mostrará qué directorios se analizan en busca de las DLL y cualquier problema de permisos que pueda tener.

Otra opción es incrustar la DLL nativa como un recurso en la DLL administrada. Esto es más complicado en ASP.NET, ya que requiere escribir en una carpeta temporal en tiempo de ejecución. La técnica se explica en otra respuesta SO .

Siempre vale comprobando ruta también en la configuración de su entorno.

Ejecute DEPENDS en XYZ.dll directamente, en la ubicación en la que lo ha implementado. Si eso no revela que falta algo, use la herramienta fuslogvw en el SDK de la plataforma para rastrear los errores del cargador. Además, los registros de eventos a veces contienen información sobre errores al cargar archivos DLL.

Me he encontrado con el mismo problema. Y probé todas las opciones anteriores, copiando a system32, inetpub, configurando el entorno de ruta, etc. nada funcionó. Este problema finalmente se resuelve copiando dll no administrado en el directorio bin de la aplicación web o servicio web.

& # 1040; después de luchar todo el día por este problema y finalmente encontré una solución que me conviene. Es solo una prueba, pero el método está funcionando.

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

En Application_start use esto: (personalice las carpetas / bin / x64 y bin / dll / x64 según sea necesario)

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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top