Domanda

Questa domanda riguarda un sito Web ASP.NET, originariamente sviluppato in VS 2005 e ora in VS 2008.

Questo sito Web utilizza due DLL esterne non gestite che non sono .NET e non ho il codice sorgente per compilarle e devono usarle così come sono.

Questo sito Web funziona correttamente da Visual Studio, individuando e accedendo correttamente a queste DLL esterne. Tuttavia, quando il sito Web viene pubblicato su un server Web (che esegue IIS6 e ASP.NET 2.0) anziché sul PC di sviluppo, non è in grado di individuare e accedere a queste DLL esterne e viene visualizzato il seguente errore:

Impossibile caricare la DLL 'XYZ.dll': impossibile trovare il modulo specificato. (Eccezione da HRESULT: 0x8007007E)

Le DLL esterne si trovano nella directory bin del sito Web, insieme alle DLL gestite che le avvolgono e tutte le altre DLL per il sito Web.

La ricerca di questo problema rivela che molte altre persone sembrano avere lo stesso problema nell'accedere a DLL esterne non.NET dai siti Web ASP.NET, ma non ho trovato una soluzione che funzioni.

Ho provato quanto segue:

  • Esecuzione di DEPENDS per verificare le dipendenze per stabilire che le prime tre sono nella directory System32 nel percorso, l'ultimo è in .NET 2 quadro.
  • Ho inserito le due DLL e le relative dipendenze System32 e riavviato il server, ma sito Web ancora impossibile caricare queste DLL esterne.
  • Ha ottenuto tutti i diritti su ASPNET, IIS_WPG e IUSR (per quel server) su la directory bin del sito Web e riavviata, ma il sito Web non è ancora riuscito carica queste DLL esterne.
  • Aggiunte le DLL esterne come elementi esistenti ai progetti e impostate loro " Copia in output " proprietà in " Copia sempre " ;, e nel sito Web non riesco ancora a trovare le DLL.
  • Imposta anche la loro azione " Build Action " proprietà a " Risorsa incorporata " e il sito Web non riesce ancora a trovare le DLL.

Qualsiasi aiuto per questo problema sarebbe molto apprezzato!

È stato utile?

Soluzione

Prova a mettere le dll nella directory \ System32 \ Inetsrv. Questa è la directory di lavoro di IIS su Windows Server.

Se questo non funziona, prova a inserire le dll nella directory System32 e i file delle dipendenze nella directory Inetsrv.

Altri suggerimenti

Ciò accade perché le dll gestite vengono copiate in ombra in una posizione temporanea nella directory di .NET Framework. Vedi http://msdn.microsoft.com/en-us/library/ms366723. aspx per i dettagli.

Sfortunatamente, le dll non gestite NON vengono copiate e il processo ASP.NET non sarà in grado di trovarle quando è necessario caricarle.

Una soluzione semplice è quella di inserire le dll non gestite in una directory che si trova nel percorso del sistema (digitare "quot" path "nella riga di comando per vedere il percorso sulla propria macchina) in modo che possano essere trovate da ASP.NET processi. La directory System32 è sempre nel percorso, quindi mettere sempre le dll non gestite lì funziona sempre, ma consiglierei di aggiungere qualche altra cartella al percorso e quindi aggiungere le dll lì per prevenire l'inquinamento della directory System32. Un grosso svantaggio di questo metodo è che devi rinominare le dll non gestite per ogni versione della tua applicazione e puoi avere rapidamente il tuo inferno di dll.

In alternativa al mettere la dll in una cartella che è già nel percorso (come system32) puoi cambiare il valore del percorso nel tuo processo usando il seguente codice

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

Quindi, quando LoadLibrary tenta di trovare la DLL non gestita, scansiona anche searchPath. Questo potrebbe essere preferibile per fare un pasticcio in System32 o altre cartelle.

Aggiungendo alla risposta di Matt, questo è quello che alla fine ha funzionato per me per il server a 64 bit 2003 / IIS 6:

  1. assicurati che dlls / asp.net abbiano la stessa versione (32/64 bit)
  2. Metti le dll non gestite nella directory inetsrv (nota che nelle finestre a 64 bit, questo è sotto syswow64, anche se viene creata la directory sys32 / inetsrv)
  3. Lascia le dll gestite in / bin
  4. Assicurati che entrambi i set di dll abbiano i permessi di lettura / esecuzione

Dai un'occhiata a FileMon o ProcMon e filtra i nomi delle DLL problematiche. Questo ti mostrerà quali directory vengono scansionate nella ricerca delle DLL e tutti i problemi di autorizzazione che potresti avere.

Un'altra opzione è incorporare la DLL nativa come risorsa nella DLL gestita. Ciò è più complicato in ASP.NET, poiché richiede la scrittura in una cartella temporanea in fase di esecuzione. La tecnica è spiegata in un'altra risposta SO .

Vale sempre la pena controllare il percorso anche nelle impostazioni del tuo ambiente.

Esegui DEPENDS su XYZ.dll direttamente, nella posizione in cui lo hai distribuito. Se ciò non rivela nulla mancante, utilizzare lo strumento fuslogvw nell'SDK della piattaforma per tracciare gli errori del caricatore. Inoltre, i registri eventi a volte contengono informazioni sugli errori nel caricamento delle DLL.

Ho riscontrato lo stesso problema. E ho provato tutte le opzioni di cui sopra, copiando su system32, inetpub, impostando l'ambiente del percorso, ecc. Niente ha funzionato. Questo problema viene infine risolto copiando la dll non gestita nella directory bin dell'applicazione Web o del servizio Web.

& # 1040; dopo aver lottato tutto il giorno per questo problema e finalmente ho trovato una soluzione adatta a me. È solo un test, ma il metodo funziona.

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

Su Application_start usa questo: (personalizza le cartelle / bin / x64 e bin / dll / x64 secondo necessità)

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top