Protokolldateiinformationen

Aktualisiert: November 2007

Sie können Protokolldateien erstellen, die Aktionen aus folgenden Vorgängen aufzeichnen:

  • Zusammenwirken mit systemeigenem Code

  • Laden von Programmen

  • Netzwerkvorgänge

Weitere Informationen über die Registrierungsschlüssel zur Steuerung der Protokollierung und über das Generieren von Protokolldateien finden Sie unter Gewusst wie: Erstellen von Protokolldateien.

In diesem Thema wird die bei Interop- und Ladeprogrammprotokollierung in Protokolldateien geschriebene Ausgabe beschrieben.

Interop-Protokolldateien

Die Ausgabe für die Interop-Protokollierung umfasst die Signaturen der während der Laufzeit stattfindenden Interop-Funktionsaufrufe sowie Fehlermeldungen.

.NET Compact Framework, Version 3.5, umfasst erweiterte Unterstützung für die Interop-Protokollierung, die weiter unten in diesem Thema unter "Tiefes Marshalling" erläutert wird.

Funktionssignaturen

Die Signaturen sowohl für Aufrufe von systemeigenem Code durch verwalteten Code als auch für Aufrufe von verwaltetem Code durch systemeigenen Code werden protokolliert und umfassen die folgenden Typen von Aufrufen:

  • Plattformaufrufe

  • COM vtable- und Dispatch-Aufrufe

  • Delegatrückrufe

Die Interop-Protokollierung kann Ihnen bei der Behandlung von Problemen helfen, die beim Aufruf einer Interop-Funktion oder bei der Rückgabe eines Interop-Funktionsaufrufs auftreten, beispielsweise wenn ein Parameter nicht wie erwartet initialisiert wird oder wenn das Programm unerwartet beendet wird.

Bei einem Funktionssignatureintrag umfasst die Ausgabe bei jedem Interop-Aufruf drei Zeilen. Die erste Zeile umfasst Flags, die den Typ des Funktionsaufrufs kennzeichnen, und enthält mindestens eines der folgenden Elemente:

  • [pinvokeimpl]
    Identifiziert einen Aufruf von systemeigenem Code durch verwalteten Code, in dem das DllImportAttribute-Attribut verwendet wird.

  • [Ctor]
    Identifiziert einen Konstruktor für eine vom Type Library Importer-Tool (Tlbimp.exe) generierte Interopassemblyklasse.

  • [preservesig]
    Es wird davon ausgegangen, dass die verwalteten und systemeigenen Funktionen die gleiche Signatur haben, wobei durch die Laufzeit keine Verschiebung von HRESULT in die Ausnahme erzwungen wird.

  • [delegate]
    Gibt an, dass die Funktion ein Delegatrückruf von systemeigenem Code auf verwalteten Code ist. Der Delegat fungiert in systemeigenem Code als Funktionszeiger.

Die zweite Zeile der Interop-Protokolldatei stellt die verwaltete Signatur dar. Bei Funktionsaufrufen von systemeigenem Code durch verwalteten Code kennzeichnet diese Zeile die verwaltete Funktion, die den systemeigenen Code aufruft. Bei Funktionsaufrufen von verwaltetem Code durch systemeigenen Code kennzeichnet diese Zeile die verwaltete Funktion, die von systemeigenem Code aufgerufen wird.

Die dritte Zeile stellt die von der Laufzeit erwartete systemeigene Signatur dar. Diese Zeile identifiziert die Datentypen für jeden Parameter und enthält Informationen darüber, wie das Marshalling der verwalteten Objektdaten durchgeführt wird. Die Laufzeit geht davon aus, dass vom DllImportAttribute-Attribut oder in der Definition der COM-Schnittstellensignatur die richtigen Typen angegeben werden. Häufig werden nicht die richtigen Typen angegeben. Dies kann zu unerwartetem Verhalten führen, da die aufgerufene Funktion mit falschen Parameterwerten ausgeführt wird.

Jeder Typ verfügt über einen Standardmarshallingtyp. Das Marshallingverhalten eines verwalteten Typs kann bei COM-Aufrufen und DllImportAttribute-Aufrufen oder Delegatrückrufen unterschiedlich sein. Mit dem MarshalAsAttribute-Attribut können Sie einen anderen Marshallingtyp als den Standardtyp angeben. Sie müssen außerdem das ref-Schlüsselwort verwenden, um Parameter zu kennzeichnen, die einen Zeiger auf einen Werttyp oder bei einem Referenztyp einen Zeiger auf einen Zeiger darstellen.

In der folgenden Tabelle wird die Interop-Protokollierung eines Plattformaufrufs dargestellt.

Zeilennummer und Beschreibung

Protokolleintrag

1 - Typ des Funktionsaufrufs

[pinvokeimpl][preservesig]

2 - Verwaltete Signatur

bool PlatformDetector::SystemParametersInfo(uint , uint , System.Text.StringBuilder , uint );

3 - Systemeigene Signatur

BOOLEAN (I1_WINBOOL_VAL) SystemParametersInfo(unsigned int (U4_VAL) , unsigned int (U4_VAL) , WCHAR * (STRINGBUILDER_LPWSTR) , unsigned int (U4_VAL) );

In der folgenden Tabelle wird die Interop-Protokollierung eines Delegatrückrufs dargestellt.

Zeilennummer und Beschreibung

Protokolleintrag

1 - Typ des Funktionsaufrufs

[preservesig][delegate]

2 - Verwaltete Signatur

int WndProc::Invoke(WndProc , IntPtr , uint , uint , int );

3 - Systemeigene Signatur

int (I4_VAL) (*)(INT_PTR (I_VAL) , unsigned int (U4_VAL) , unsigned int (U4_VAL) , int (I4_VAL) )

In der folgenden Tabelle wird die Interop-Protokollierung eines COM-Funktionsaufrufs von verwaltetem Code durch systemeigenen Code dargestellt, wobei die Laufzeit bei einer verwalteten Ausnahme ein Fehler-HRESULT zurückgibt.

Zeilennummer und Beschreibung

Protokolleintrag

1 - Typ des Funktionsaufrufs

(keine Flags)

2 - Verwaltete Signatur

int N2MDualComponentImp.IN2MDualInterface::GetInt(N2MDualComponentImp.IN2MDualInterface This);

3 - Systemeigene Signatur

HRESULT GetInt(IN2MDualInterface *(INTF_VAL) this, [retval] int (I4_VAL) retval);

Tiefes Marshalling

.NET Compact Framework, Version 3.5, unterstützt auch tiefes Marshalling für die Interop-Protokollierung. Beim tiefen Marshalling werden Informationen über gemarshallte Objekte, die sich in Strukturen oder in Referenztypen befinden, protokolliert.

Die folgende Protokollausgabe zeigt ein Beispiel für einen Plattformaufruf, der in einer Struktur enthaltene gemarshallte Objekte verwendet. In der ersten Zeile des Abschnitts für tiefes Marshalling wird angegeben, warum der tiefe Marshaller aufgerufen wurde. In diesem Beispiel wurde er aufgerufen, um die Größe der Struktur zu berechnen. Das Protokoll zeigt den Datentyp und die Größe der einzelnen Objekte in Byte an. Die Indexwerte (z. B. 0004) stellen die Byteoffsets für die angegebenen Variablen dar.

DEEP MARSHAL: Get size
struct interoplogging.MyStruct
{
0000: Int32 myVar as Int32 (4 bytes)
0004: Int32 myVar2 as Int32 (4 bytes)
0008: String myString as WCHAR[10] (20 bytes)
}
DEEP MARSHAL: Total size = 28 bytes

[pinvokeimpl][preservesig]
void  interoplogging.Form1::MyAPI(interoplogging.MyStruct );
void MyAPI(MyStruct (NONBLIT_VALUETYPE_VAL) );

DEEP MARSHAL: Managed -> Native
struct interoplogging.MyStruct
{
0000: Int32 myVar as Int32 (4 bytes)
0004: Int32 myVar2 as Int32 (4 bytes)
0008: String myString as WCHAR[10] (20 bytes)
}
DEEP MARSHAL: Total size = 28 bytes

Fehlermeldungen

In bestimmten Situationen und bei bestimmten Ausnahmen werden in der Protokolldatei unter Umständen Fehlermeldungen aufgezeichnet. Diese Meldungen können besonders hilfreich sein, wenn Probleme untersucht werden, die das Zusammenwirken mit systemeigenen Komponenten und DLLs betreffen, für die der systemeigene Quellcode nicht zur Verfügung steht. Fehlermeldungen können bei folgenden Problemen hilfreich sein:

  • Funktionsaufrufe von verwaltetem Code durch systemeigenen Code.

  • Laufzeit-COM-Schnittstellenaufrufe. Ein HRESULT-Fehler kann an systemeigenen Code zurückgegeben werden, wenn eine von der Laufzeit implementierte COM-Schnittstellenfunktion aufgerufen wird. Es gibt verschiedene von der Laufzeit implementierte Schnittstellen (einschließlich IUnknown, IDispatch, IConnectionPointContainer, IEnumConnectionPoints und IConnectionPoint), die von systemeigenem Code mithilfe eines verwalteten Objekts aufgerufen werden können, das als COM-Schnittstelle gemarshallt wird. Wenn ein Funktionsaufruf einen Fehler an systemeigenen Code in einer dieser Schnittstellen zurückgibt, druckt die Laufzeit eine entsprechende Fehlermeldung, wobei das HRESULT und zusätzliche relevante Informationen angegeben werden.

  • Systemeigener Code, der nicht unterstützte Funktionen verwenden soll, z. B. IDispatch::GetTypeInfo.

  • Nicht implementierte Schnittstellen. Systemeigener Code kann von IUnknown::QueryInterface einen E_NONINTERFACE-Fehler empfangen, wenn der Code erwartet, dass das verwaltete COM-Objekt eine zusätzliche Schnittstelle implementiert hat. In diesem Fall wird die GUID der nicht implementierten Schnittstelle ebenfalls angegeben.

  • Verwaltete Ausnahmen. Diese können im verwalteten Funktionsaufruf auftreten und bewirken, dass Werte vorzeitig zurückgegeben werden. Beim Ausführen eines COM-Aufrufs konvertiert die Laufzeit die Ausnahme in einen HRESULT-Fehlerwert und gibt diesen an den systemeigenen Code zurück. Bei Delegatrückrufen und COM-Aufrufen, die keine HRESULT-Rückgabewerte erwarten, gibt es jedoch keine Möglichkeit sicherzustellen, dass der Fehler erkannt wird, sodass es eventuell zu unerwartetem Verhalten kommt. Das Interop-Protokoll enthält eine Fehlermeldung, wenn während eines Interop-Funktionsaufrufs von verwaltetem Code durch systemeigenen Code eine Ausnahme auftritt. Mithilfe dieser Fehlermeldung können Sie verwaltete Funktionen identifizieren, die eine zusätzliche Fehlerbehandlungslogik benötigen, damit sie mit systemeigenem Code harmonieren. Die folgenden Faktoren können eine verwaltete Ausnahme verursachen:

    • Wenn Sie in der COM-Schnittstellendefinition oder der DllImportAttribute-Signatur Typen verwenden, die von .NET Compact Framework nicht unterstützt werden, wird während der JIT-Kompilierung eine Ausnahme ausgelöst. Häufig gibt es zulässige Alternativen, z. B. IntPtr.

    • Wenn das eigentliche Objekt nicht in den Typ konvertiert werden kann, der in der Signatur angegeben ist, oder wenn die Objektdaten nicht in den angeforderten Typ konvertiert werden können, wird beim Aufruf der Funktion zur Laufzeit eine Ausnahme ausgelöst. Dies geschieht normalerweise bei der Konvertierung eines systemeigenen Objekts in ein verwaltetes Objekt.

    • Es ist schwierig festzustellen, wodurch eine Ausnahme verursacht wird, wenn ein Runtime Callable Wrapper (RCW) oder ein COM Callable Wrapper (CCW) erstellt wird. Mithilfe der Interop-Protokolldatei lässt sich die Ursache dieser Probleme ermitteln, wenn bei der verwalteten Ausnahme keine detaillierte Fehlermeldung angezeigt wird.

Unterschiede zu .NET Framework

Die COM-Interoperabilität ist in .NET Compact Framework und der Vollversion von .NET Framework unterschiedlich implementiert. .NET Compact Framework unterstützt die folgenden Funktionen nicht:

  • Erstellen eines CCW, der eine Schnittstelle ohne eine angegebene GUID enthält.

  • Erstellen eines RCW für eine Klasse, die von einer Interopassemblyklasse erbt.

  • Erstellen eines CCW, der eine nicht generische Schnittstelle mit einer generischen Methode enthält.

RCWs werden beim Abschluss in der Regel bereinigt. Sie können jedoch auch die ReleaseComObject-Methode oder die FinalReleaseComObject-Methode verwenden, um den einem Objekt zugeordneten RCW freizugeben. Wenn Sie diese erweiterten Optionen zur Verwaltung der Lebensdauer der Objekte verwenden und versuchen, das Objekt nach seiner Freigabe für einen systemeigenen COM-Aufruf zu verwenden, wird eine Ausnahme ausgelöst. Die Protokolldatei enthält dann eine Fehlermeldung zur Ursache der Ausnahme.

Ladeprogrammprotokolldateien

Ladeprogrammprotokolldateien bestehen aus zwei Abschnitten: dem Header und dem Text. Der Header der Protokolldatei enthält die folgenden Daten:

  • Name der ausführbaren Hauptdatei der Anwendung

  • Die vom Betriebssystem zugewiesene Prozess-ID

  • Datum und Uhrzeit, zu der die Protokolldatei erstellt wurde

  • Versionsbezeichnung von .NET Compact Framework, die zur Ausführung der Anwendung verwendet wird

  • Informationen über die Plattform, auf der die Anwendung ausgeführt wird

Der Text der Protokolldatei enthält Diagnoseinformationen über die einzelnen Assemblys, die von der Anwendung geladen werden. Diese Informationen können Sie dabei unterstützen, von Klassenladeprogramm ermittelte Fehler beim Starten der Anwendung zu finden.

Der Text der Protokolldatei enthält die folgenden Daten:

  • Koersionszustand, der angibt, ob die Anwendung im Abwärtskompatibilitätsmodus ausgeführt wurde

  • Ablaufverfolgung für jeden Assemblyladevorgang, einschließlich Angabe des Orts, von dem die Assembly geladen wurde, sowie der Version, die geladen wurde

  • Vertrauensstufe, die den einzelnen Modulen beim Laden zugewiesen wurde

  • Konfigurationsdateien, die der Anwendung zugeordnet sind

  • Nicht gefundene Methoden, Typen, Assemblys und Module

  • Nicht gefundene systemeigene DLLs oder Funktionen für einen Plattformaufruf

In der folgenden Tabelle ist ein Beispiel für eine Ladeprogrammprotokolldatei dargestellt. Die Zeilennummern sind hier nur ungefähre Angaben.

Zeilennummer und Beschreibung

Protokolleintrag

1 - Prozess

Process [\Program Files\VW\VW.exe]

2 - Prozess-ID

Process ID [0x4d9585d2]

3 - Datum

Date [2005/02/25]

4 - Uhrzeit

Time [18:33:14]

5 - .NET Compact Framework-Version

NETCF [2.0.5035.00]

6 - Plattform

Platform [Windows CE v4.20.1081 (PocketPC) WinCE4ARMV4 release Beta2 ARMV4 IJITv2]

7-14 - Globale Assemblycachevorgänge

GAC: Updating GAC [0x0]

GAC: Checking .gac files inside [\Windows\]

GAC: Found [Microsoft .NET CF 2.0.GAC] .gac file.

GAC: Done with the file system check. Checking the registry.

GAC: Found [Microsoft .NET CF 2.0.GAC] registry entry.

GAC: Done with the registry check. Let's compare.

GAC: Entry [Microsoft .NET CF 2.0.GAC] is up to date.

GAC: GAC is up to date.

15 - Kompatibilitätsmodus (0.0.0.0 gibt an, dass kein Kompatibilitätsmodus vorliegt)

Compatibility mode [0.0.0.0]

16 - Ladendes Modul

Loading module [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll]

17 - Geladenes Modul

Loaded [mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969DB8053D3322AC] from [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll]

Für jedes Modul werden die letzten beiden Einträge (Loading und Loaded) protokolliert. Sie geben die Assemblys und deren Speicherorte an. Alle beim Laden eines Moduls aufgetretenen Fehler werden im Ladeprogrammprotokoll angegeben.

Beispiele für Fehler

Die beiden folgenden Beispiele in diesem Abschnitt zeigen, wie Sie mithilfe der Ladeprogrammprotokolldatei feststellen können, wann Fehler aufgetreten sind.

Im folgenden Beispiel werden die Protokolleinträge gezeigt, die geschrieben werden, wenn das Ladeprogramm eine Assembly nicht finden kann:

Loading module [\Program Files\VW\Golf.dll]
Attempt to load [\Program Files\VW\Golf.dll] has failed (err 0x80001000).
Loading module [\Program Files\VW\Golf.exe]
Attempt to load [\Program Files\VW\Golf.exe] has failed (err 0x80001000).
Failed to load [Golf, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]

Im folgenden Beispiel werden die Protokolleinträge gezeigt, die geschrieben werden, wenn das Ladeprogramm einen bestimmten Typ nicht finden kann.

Missing Type. Type [Cars.Jetta], Assembly [Cars].
Missing Type. Class [Cars.Jetta], Assembly [Cars, Version=5.0.0.0, 
Culture=neutral, PublicKeyToken=null].

Siehe auch

Aufgaben

Gewusst wie: Erstellen von Protokolldateien

Gewusst wie: Konfigurieren der Laufzeitversion

Konzepte

Gewusst-wie-Themen für .NET Compact Framework

Weitere Ressourcen

Interoperabilität in .NET Compact Framework

Leistung und Diagnose in .NET Compact Framework