2 Stimmen

Warum erhalte ich einen Assembly-Bind-Fehler im IIS-CGI-Programm?

Ich habe ein C#-Programm, das als eine CGI-Anwendung in IIS auf XP Pro SP3 ausgeführt wird. Es läuft gut, bis ich auf eine Bibliotheks-Assembly-Klasse verweise und sie im Code des Programms verwende. Wenn ich das CGI-Programm von Hand ausführe, wird es geladen und ausgeführt. Aber wenn es von IIS ausgeführt wird, kann die referenzierte Assembly nicht gebunden werden, obwohl sie sich im selben Verzeichnis wie die übergeordnete ausführbare Datei befindet. Hier ist das Bindungsprotokoll, das ich erhalte:

\=== Pre-bind state information ===
LOG: User = STEVIENEW\\IUSR\_STEVIENEW
LOG: DisplayName = VOEvent, Version=3.0.7.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/
LOG: Initial PrivatePath = NULL
Calling assembly : MsgChkCGI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from c:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\config\\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent.DLL.
LOG: Attempting download of new URL file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent/VOEvent.DLL.
LOG: Attempting download of new URL file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent.EXE.
LOG: Attempting download of new URL file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent/VOEvent.EXE.

Die Appbase ist korrekt (obwohl, was ist das '?' in der URI????? vielleicht ist das ein Hinweis). Die Assembly voevent.dll befindet sich definitiv im selben Verzeichnis (Appbase!) wie MsgChkCGI.exe. Und wenn ich einfach auf die Exe doppelklicke, wird sie korrekt gestartet (und hat einen Fehler wegen einer fehlenden CGI-Umgebungsvariable, aber das ist zu erwarten).

Weiß jemand, was hier los ist?

3voto

SLaks Punkte 832502

Ich bin mir nicht sicher, warum das passieren könnte.

Als Abhilfe könnten Sie Folgendes behandeln AppDomain.CurrentDomain.AssemblyResolve

EDIT : Wenn Sie in derselben Methode, die den Handler hinzufügt, Typen einer anderen Assembly verwenden, wird das Ereignis nicht ausgelöst, da die Assembly vom JITter geladen wird, bevor der Code in der Methode tatsächlich ausgeführt wird.
Daher müssen Sie jeden Code, der Typen aus anderen Assemblies verwendet, in einer separaten Methode unterbringen und diese Methode dann nach der Behandlung von AssemblyResolve .

2 und EDIT : Rufen Sie an. Assembly.Load(File.ReadAllBytes(path)) .
Könnten Sie außerdem Ihre Frage so bearbeiten, dass sie alle Einzelheiten der FileNotFoundException von Assembly.LoadFile ?

1voto

xmedeko Punkte 6370

Auf der Grundlage der Antwort von SLaks habe ich die Lösung geschrieben

Assembly assembly = Assembly.GetEntryAssembly();
Uri codeBaseUrl = new Uri(assembly.CodeBase);
// hack IIS CGI malformed url
if (codeBaseUrl.ToString().StartsWith("file:///?/"))
    codeBaseUrl = new Uri("file:///" + codeBaseUrl.ToString().Substring(10));
string dir = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
dir = Path.GetDirectoryName(dir);

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var dllName = new AssemblyName(args.Name).Name + ".dll";
    dllName = Path.Combine(dir, dllName);

    return Assembly.LoadFile(dllName);
};

Andere Teile von .NET schlagen jedoch aufgrund der fehlerhaften URL fehl file:///?/ Deshalb möchte ich die Lösung wissen, wie man die URL nicht ändern muss.

0voto

xmedeko Punkte 6370

Eine andere Lösung ist, den Prozess mit der EXE aus einem anderen CGI zu starten, z.B. aus PHP, anotehr EXE oder CMD.

Um die *.cmd als CGI zu verwenden, geben Sie ein einfaches CMD-Skript ein, das die EXE ausführt

@echo off
%~dp0\myprogram.exe

Und konfigurieren Sie den IIS so, dass CMD als CGI ausgeführt wird. Machen Sie dasselbe wie bei der EXE-Datei, geben Sie einfach Ihr CMD in den richtigen Einstellungen ein. Gehen Sie dann zum Handler-Zuordnungen wählen CGI-exe und ändern Sie die *.exe a *.cmd . Gehen Sie schließlich zum CGI-Panel und ändern Sie die Neue Konsole verwenden... a Wahr .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X