2009-04-07 11 views
4

Das Erstellen einer WCF-Dienstbibliothek in Visual Studio 2008 auf Vista x64 ist mühsam beim Verweisen auf eine x86-DLL. Ein Dienst, der eine 32-Bit-DLL aufruft, muss ein Plattformziel von x86 für die Ausführung auf einem 64-Bit-Betriebssystem haben. Wenn Sie das tun, löst der WcfSvcHost eine BadImageFormatException aus, wenn Sie versuchen, den Dienst zu debuggen. Es gibt eine bug report auf MS connect. Die Problemumgehung, die ich verwendet habe, war coreflag WcfSvcHost as 32-bit.BadImageFormatException bei WcfSvcHost und IIS WCF-Host

Manifest Problem

Das Hauptproblem ich habe laufen in dieser Drittpartei ist native 32-Bit-DLL nicht Hosts mit bestimmten WCF zu laden. Ich erhalte die folgende Fehlermeldung, wenn ein Service-Betrieb wird aufgerufen, die die Drittanbieter-DLL verwendet:

System.TypeInitializationException: Die Typeninitialisierer für ‚‘ hat eine Ausnahme.

.ModuleLoadExceptionHandlerException: Eine verschachtelte Ausnahme auftrat, nachdem die primäre Ausnahme, dass die C++ Modul verursacht nicht geladen werden.

System.BadImageFormatException: Das Modul sollte ein Assemblymanifest enthalten. (Ausnahme von HRESULT: 0x80131018)

NestedException:

Der Griff ist ungültig. (Ausnahme von HRESULT: 0x80070006 (E_HANDLE))

Diese Ausnahme wird ausgelöst, wenn nicht WcfSvcHost gestartet wird, erhöht ist, wenn die ein Service-Operation aufgerufen wird, dass die DLL 32-Bit verweist. Was sehr interessant ist, mit der gleichen app.config auf einer Konsole App den gleichen Service-Hosting hat keine Ausnahmen und funktioniert perfekt:

using (ServiceHost host = new ServiceHost (typeof (MsgBrokerService))) { 
    host.Open(); 
    Console.WriteLine ("running"); 
    Console.ReadLine(); 

Diese Ausnahme tritt direkt nach:

‚WcfSvcHost.exe‘ (Managed): geladen 'C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll'

Auch hier hat die Konsolenanwendung nicht eine exceptio haben n und lädt die gleiche DLL:

'ConsoleApp.vshost.exe' (verwaltet): Loaded ‚C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll '

Siehe Antwortfrom Microsoft Product Support.

Update # 1: Sowohl die Konsolenanwendung als auch der Hostprozess WcfSvcHost.exe laufen unter derselben Sitzung und dem angemeldeten Benutzer (me). Ich habe WcfSvcHost kopiert.exe in das Verzeichnis des Dienstes, manuell gestartet und das gleiche Ergebnis erfahren. Ich habe auch das Windows-Ereignisprotokoll für zusätzliche Informationen überprüft und sxstrace verwendet, aber nichts wurde protokolliert.

Lauf Process Explorer, habe ich überprüft die folgenden sind auch zwischen den beiden Prozessen:

  • Image: 32-Bit-
  • Aktuelles Verzeichnis
  • Benutzer/SID
  • Session
  • Sicherheit (Gruppen verweigert, Privilegien deaktiviert)

Running Process Monitor und configuring symbols, sehe ich WcfSvcHost sucht nach der folgenden Registrierung und Dateien, während der Konsolenhost nicht. Process Monitor protokolliert eine Menge Daten, und ich bin nicht sicher, was ich suche :(

HKLM \ SOFTWARE \ Microsoft \ Fusion \ publisherpolicy \ Default \ policy.8.0.msvcm80__b03f5f7f11d50a3a C.: \ windows \ assembly \ GAC_32 \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C: \ WINDOWS \ assembly \ GAC_MSIL \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C: \ WINDOWS \ assembly \ GAC \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a

Update # 2: Dieselbe Ausnahme tritt auf, wenn der Dienst in der Produktion gehostet wird auf IIS 6/Windows Server 2003

Update # 3: Die 3rd-Party-32-Bit-NET-Assembly ist der StreamBase API:

  • sbclient.dll (verwaltet)
  • monitor.netmodule (verwaltet)
  • dotnetapi.dll (unmanaged)
  • pthreads-vc8.dll (unmanaged)

Update # 4: Added Manifeste ohne Erfolg:

  1. überprüft, dass dotnetapi.dll und pthreads-vc8.dll haben RT_MANIFEST. Die sbclient.dll .NET Assembly hatte keinen offensichtlichen
  2. aus dem GAC
  3. entfernt sbclient.dll
  4. Registrierte sbclient.dll zur Überprüfung
  5. Added ein Manifest über mt.exe sowohl sbclient.dll Überspringen und monitor.netmodule
  6. Verifiziertes Manifest wurde hinzugefügt und die erwarteten Dateien wurden während des Tests geladen (über Visual Studio - Fenster Debug-Module)
  7. Die gleiche BadImageFormatException wird unter BackgroundWorker.OnDoWork() ausgelöst, und die Aufrufliste zeigt einen Aufruf von dotnetapi.dll ... DefaultDomain.Initialisierung().

Ich habe das msvcm80 verifiziert.dll keine offenkundige haben, ich glaube, dass dies die einzige Datei ist, dass geladen hat keinen offensichtlichen :)

Interessante

finden Als ich monitor.netmodule in Reflector laden, heißt es:

'monitor.netmodule' enthält kein Manifest einer Baugruppe.

Obwohl Reflector einen Fehler anzeigt, kann der verwaltete Code dennoch zerlegt werden.

+1

Was ist die 32-Bit-DLL von Drittanbietern und was macht sie? –

+0

StreamBase - Details über –

+0

Vielleicht wollen die Autoren der DLL nicht konsumiert werden und haben irgendeine Art von bösem Verschleierer angewendet, um die DLL zu zerstören, wenn Sie versuchen, sie zu importieren? – Spence

Antwort

1

Microsoft Product Support hat diese Frage gelöst: Es ist von Entwurf. Der nicht verwaltete Code wird nicht in der Standard-AppDomain geladen, wenn WcfSvcHost oder der IIS WCF-Host verwendet wird.

Ein reines Bild verwendet eine CLR-Version der C-Laufzeitbibliothek. Allerdings ist die CRT nicht überprüfbar, so dass Sie nicht CRT verwenden können, wenn Sie mit /clr: safe kompilieren. Weitere Informationen finden Sie unter C Laufzeitbibliotheken.

http://msdn.microsoft.com/en-us/library/k8d11d4s.aspx

0

Ich kann keine Erklärung für den Fehler liefern, nur meinen anfänglichen Verdacht, dass es einen Erlaubnisunterschied zwischen dem Kontext gibt, in dem Ihr Code als Dienst ausgeführt wird, und dem Kontext, in dem er ausgeführt wird, wenn Sie ihn in einer Konsole platzieren Anwendung. Das E_HANDLE HRESULT ist mein Anhaltspunkt hier. Wenn Sie die Konsolenanwendung als angemeldeten Benutzer ausführen, können Sie versuchen, den Dienst so zu konfigurieren, dass er als dieser Benutzer gestartet wird. Wenn es in dieser Konfiguration funktioniert, können Sie versuchen, einzuschränken, welche erforderliche Ressource bei einem Fehler nicht verfügbar ist.

Ich kann eine Problemumgehung vorschlagen. Wenn es eine Kuriosität der betreffenden DLL gibt, die verhindert, dass sie in einem gehosteten Dienst funktioniert, können Sie den Opferprozessansatz verwenden, der so genannt wird, weil er normalerweise verwendet wird, um eine DLL zu isolieren, die häufig abstürzt. Kurz gesagt, erstellen Sie ein Proxy-Programm, dessen einziger Zweck darin besteht, die DLL im Auftrag Ihres Hauptprozesses zu laden und aufzurufen, wobei Named Pipes oder eine andere IPC-Methode verwendet wird, um Anforderungen und Ergebnisse zu übergeben. Wenn die DLL abstürzt, starten Sie eine neue Instanz des Proxy-Programms. In Ihrem Fall hätte es den zusätzlichen Vorteil, dass nur das Wrapper-Programm 32-Bit sein müsste.

0

Sehen Sie etwas Besonderes in der Ereignisanzeige ?.
In Vista, wenn es ein offensichtliches Problem gibt, werden Sie Spuren davon in der Ereignisanzeige sehen, es wird Ihnen sagen, SxsTrace zu verwenden.

4

ein bisschen spät, aber Sie können auch den App-Pool ändern "Enable 32-Bit-Anwendungen" auf true in der erweiterten Einstellungen festlegen.

0

Das mag ein bisschen dumm erscheinen; Stellen Sie jedoch sicher, dass Ihr Dienst im richtigen Anwendungspool ausgeführt wird.

+0

Es war ein Fehler im 3rd Party Code. –