it-swarm.com.de

Nicht verwaltete DLLs können auf dem ASP.NET-Server nicht geladen werden

Diese Frage bezieht sich auf eine ASP.NET-Website, die ursprünglich in VS 2005 und jetzt in VS 2008 entwickelt wurde.

Diese Website verwendet zwei nicht verwaltete externe DLLs, bei denen es sich nicht um .NET handelt, und ich habe nicht den Quellcode, um sie zu kompilieren und sie so zu verwenden, wie sie sind.

Diese Website wird problemlos in Visual Studio ausgeführt und sucht nach diesen externen DLLs und greift auf sie ordnungsgemäß zu. Wenn die Website jedoch auf einem Webserver (unter IIS6 und ASP.NET 2.0) und nicht auf dem Entwicklungs-PC veröffentlicht wird, kann sie diese externen DLLs nicht finden und darauf zugreifen, und es wird der folgende Fehler angezeigt:

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

Die externen DLLs befinden sich im bin-Verzeichnis der Website, zusammen mit den verwalteten DLLs, die sie umschließen, und allen anderen DLLs für die Website.

Das Durchsuchen dieses Problems zeigt, dass viele andere Personen anscheinend dasselbe Problem beim Zugriff auf externe Nicht-.NET-DLLs von ASP.NET-Websites haben, aber ich habe keine Lösung gefunden, die funktioniert.

Ich habe Folgendes versucht:

  • Ausführen von DEPENDS, um die Abhängigkeiten zu überprüfen und festzustellen, ob sich die ersten drei im System32-Verzeichnis im Pfad befinden, und die letzte im .NET 2-Framework.
  • Ich habe die beiden DLLs und ihre Abhängigkeiten in System32 abgelegt und den Server neu gestartet, aber die Website konnte diese externen DLLs immer noch nicht laden.
  • Erteilte ASPNET, IIS_WPG und IUSR (für diesen Server) die vollen Rechte für das Website-Bin-Verzeichnis und wurde neu gestartet, aber die Website konnte diese externen DLLs immer noch nicht laden.
  • Die externen DLLs wurden als vorhandene Elemente zu den Projekten hinzugefügt und ihre Eigenschaft "In Ausgabe kopieren" auf "Immer kopieren" festgelegt, und die DLLs werden von der Website immer noch nicht gefunden.
  • Setzen Sie außerdem die Eigenschaft "Build Action" auf "Embedded resource" (Eingebettete Ressource), und die DLLs werden von der Website immer noch nicht gefunden.

Jede Hilfe bei diesem Problem wäre sehr dankbar!

66
Werg38

Versuchen Sie, die DLLs im Verzeichnis\System32\Inetsrv abzulegen. Dies ist das Arbeitsverzeichnis für IIS unter Windows Server.

Wenn dies nicht funktioniert, versuchen Sie, die DLLs im Verzeichnis System32 und die Abhängigkeitsdateien im Verzeichnis Inetsrv abzulegen.

22
Matt

Dies liegt daran, dass die verwalteten DLLs in einen temporären Speicherort im .NET Framework-Verzeichnis kopiert werden. Weitere Informationen finden Sie unter http://msdn.Microsoft.com/en-us/library/ms366723.aspx .

Leider werden die nicht verwalteten DLLs NICHT kopiert und der ASP.NET-Prozess kann sie nicht finden, wenn sie geladen werden müssen.

Eine einfache Lösung besteht darin, die nicht verwalteten DLLs in ein Verzeichnis zu stellen, das sich im Systempfad befindet (geben Sie "path" in die Befehlszeile ein, um den Pfad auf Ihrem Computer anzuzeigen), damit sie vom ASP.NET-Prozess gefunden werden können. Das System32-Verzeichnis ist immer im Pfad, daher funktioniert es immer, die nicht verwalteten DLLs dort abzulegen, aber ich würde empfehlen, dem Pfad einen anderen Ordner hinzuzufügen und dann hinzuzufügen die DLLs dort, um eine Verschmutzung des System32-Verzeichnisses zu verhindern. Ein großer Nachteil dieser Methode ist, dass Sie die nicht verwalteten DLLs für jede Version Ihrer Anwendung umbenennen müssen und schnell Ihre eigene DLL-Hölle haben können.

44
onedozenbagels

Alternativ zum Ablegen der DLL in einem Ordner, der sich bereits im Pfad befindet (z. B. system32), können Sie den Pfadwert in Ihrem Prozess mithilfe des folgenden Codes ändern

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

Wenn LoadLibrary dann versucht, den nicht verwalteten DLL zu finden, wird auch searchPath durchsucht. Dies ist möglicherweise vorzuziehen, um ein Durcheinander in System32 oder anderen Ordnern zu verursachen.

41
Matt Woodard

Zusätzlich zu Matts Antwort funktionierte dies für mich schließlich für den 64-Bit-Server 2003/IIS 6:

  1. stellen Sie sicher, dass Ihre DLLs/asp.net die gleiche Version haben (32/64-Bit)
  2. Fügen Sie die nicht verwalteten DLLs in das Verzeichnis inetsrv ein (beachten Sie, dass sich diese in 64-Bit-Fenstern unter syswow64 befindet, obwohl das Verzeichnis sys32/inetsrv erstellt wurde).
  3. Lassen Sie die verwalteten DLLs in/bin
  4. Stellen Sie sicher, dass beide DLL-Sätze über Lese-/Ausführungsberechtigungen verfügen
11
dave

Schauen Sie mit FileMon oder ProcMon nach und filtern Sie nach den Namen der problematischen DLLs. Dies zeigt Ihnen, welche Verzeichnisse auf der Suche nach den DLLs durchsucht werden und welche Berechtigungsprobleme Sie möglicherweise haben.

6
Arnout

Eine andere Option ist das Einbetten der systemeigenen DLL als Ressource in die verwaltete DLL. Dies ist in ASP.NET komplizierter, da zur Laufzeit in einen temporären Ordner geschrieben werden muss. Die Technik wird in einer anderen SO answer erklärt.

3
yzorg

Immer wert Überprüfung des Pfads Variable in Ihren Umgebungseinstellungen.

2
annakata

Ich bin auf dasselbe Problem gestoßen. Und ich habe alle oben genannten Optionen ausprobiert, auf system32 kopiert, inetpub eingestellt, die Pfadumgebung festgelegt usw. Es hat nichts funktioniert. Dieses Problem wird endgültig behoben, indem nicht verwaltete DLLs in das bin-Verzeichnis der Webanwendung oder des Webdienstes kopiert werden.

1
Ram Chavakula

Führen Sie DEPENDS auf XYZ.dll direkt an dem Speicherort aus, an dem Sie es bereitgestellt haben. Wenn dies nichts Fehlendes anzeigt, verwenden Sie das Tool fuslogvw im Plattform-SDK, um Loader-Fehler zu verfolgen. Außerdem enthalten die Ereignisprotokolle manchmal Informationen zu Fehlern beim Laden von DLLs.

1
jlew

Nachdem ich mich den ganzen Tag über dieses Problem gestritten hatte, fand ich endlich eine Lösung, die zu mir passt. Es ist nur ein Test, aber die Methode funktioniert.

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
Mad Dog

Verwenden Sie bei Application_start Folgendes: (Passen Sie die Ordner/bin/x64 und bin/dll/x64 nach Bedarf an.)

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);
0
Ers