Informations sur le fichier journal
Mise à jour : novembre 2007
Vous pouvez créer des fichiers journaux qui enregistrent des actions pour les opérations suivantes :
Interaction avec le code natif.
Chargement de programmes.
Réseau.
Pour plus d'informations sur les clés de Registre qui contrôlent l'enregistrement dans les journaux et sur la procédure à suivre pour générer des fichiers journaux, consultez Comment : créer des fichiers journaux.
Cette rubrique décrit la sortie écrite dans les fichiers journaux pour l'enregistrement de l'interopérabilité et du chargeur.
Fichiers journaux d'interopérabilité
La sortie pour l'enregistrement de l'interopérabilité se compose des signatures des appels de fonction d'interopérabilité tels qu'ils se produisent au moment de l'exécution, avec les messages d'erreur éventuels.
Le .NET Compact Framework version 3.5 inclut une prise en charge améliorée de l'enregistrement d'interopérabilité, qui est décrite dans la section « Marshaling profond » , plus loin dans cette rubrique.
Signatures de fonction
Les signatures pour les appels du code managé au code natif et du code natif au code managé sont enregistrées et incluent les types d'appels suivants :
Appels de code non managé.
Appels vtable COM et Dispatch.
Rappels de délégués.
L'enregistrement d'interopérabilité peut vous aider à résoudre des problèmes lors de l'appel ou du retour d'un appel de fonction d'interopérabilité, par exemple lorsqu'un paramètre n'est pas initialisé comme prévu ou lorsque le programme se termine de façon inattendue.
La sortie pour une entrée de signature de fonction se compose de trois lignes pour chaque appel d'interopérabilité. La première ligne fournit les indicateurs identifiant le type d'appel de fonction effectué et comporte un ou plusieurs des éléments suivants :
[pinvokeimpl]
Identifie un appel du code managé au code natif qui utilise l'attribut DllImportAttribute.[Ctor]
Identifie un constructeur pour une classe d'assembly d'interopérabilité, générée par Type Library Importer (Tlbimp.exe).[preservesig]
Suppose que les fonctions managées et natives ont la même signature, sans traduction de HRESULT vers l'exception appliquée par le runtime.[delegate]
Indique que la fonction est un rappel de délégué du code natif au code managé. Le délégué agit comme un pointeur fonction en code natif.
La deuxième ligne du fichier journal d'interopérabilité représente la signature managée. Pour les appels de fonction du code managé au code natif, cette ligne identifie la fonction managée qui appelle le code natif. Pour les appels de fonction du code natif au code managé, cette ligne identifie la fonction managée qui est appelée à partir du code natif.
La troisième ligne représente la signature native, telle que prévue par le runtime. Cette ligne identifie les types de données pour chaque paramètre et fournit des informations sur la façon dont les données de l'objet managé sont marshalées. Le runtime suppose que les types corrects sont spécifiés par l'attribut DllImportAttribute ou dans la définition de signature d'interface COM. Une erreur courante est de ne pas spécifier les types corrects, ce qui peut provoquer un comportement inattendu car la fonction appelée sera exécutée avec des valeurs de paramètre inexactes.
Chaque type a un type de marshaling par défaut. Notez que le comportement de marshaling d'un type managé peut être différent suivant les appels COM et DllImportAttribute ou les rappels de délégué. Vous pouvez utiliser l'attribut MarshalAsAttribute pour spécifier un type de marshaling autre que le type par défaut. Vous devez également utiliser le mot clé ref pour identifier tout paramètre qui représente un pointeur vers un type valeur ou un pointeur vers un pointeur, pour un type référence.
Le tableau suivant affiche l'enregistrement d'interopérabilité d'un appel de code non managé.
Numéro de ligne et description |
Entrée de journal |
---|---|
1 - Type d'appel de fonction |
[pinvokeimpl][preservesig] |
2 - Signature managée |
bool PlatformDetector::SystemParametersInfo(uint , uint , System.Text.StringBuilder , uint ); |
3 - Signature native |
BOOLEAN (I1_WINBOOL_VAL) SystemParametersInfo(unsigned int (U4_VAL) , unsigned int (U4_VAL) , WCHAR * (STRINGBUILDER_LPWSTR) , unsigned int (U4_VAL) ); |
Le tableau suivant affiche l'enregistrement d'interopérabilité d'un rappel de délégué.
Numéro de ligne et description |
Entrée de journal |
---|---|
1 - Type d'appel de fonction |
[preservesig][delegate] |
2 - Signature managée |
int WndProc::Invoke(WndProc , IntPtr , uint , uint , int ); |
3 - Signature native |
int (I4_VAL) (*)(INT_PTR (I_VAL) , unsigned int (U4_VAL) , unsigned int (U4_VAL) , int (I4_VAL) ) |
Le tableau suivant affiche l'enregistrement d'interopérabilité d'un appel de fonction COM du code natif au code managé, où le runtime retourne une valeur HRESULT d'échec en cas d'exception managée.
Numéro de ligne et description |
Entrée de journal |
---|---|
1 - Type d'appel de fonction |
(aucun indicateur) |
2 - Signature managée |
int N2MDualComponentImp.IN2MDualInterface::GetInt(N2MDualComponentImp.IN2MDualInterface This); |
3 - Signature native |
HRESULT GetInt(IN2MDualInterface *(INTF_VAL) this, [retval] int (I4_VAL) retval); |
Marshaling profond
Le .NET Compact Framework version 3.5 prend en charge également le marshaling profond pour l'enregistrement d'interopérabilité. Dans le marshaling profond, les informations sont enregistrées à propos des objets marshalés qui sont contenus dans les structures ou dans les types référence.
La sortie de journal suivante montre un exemple d'appel de code non managé qui utilise des objets marshalés contenus dans une structure. La première ligne de la section de marshaling profond spécifie pourquoi le marshaleur profond a été appelé. Dans cet exemple, il a été appelé pour calculer la taille de la structure. Le journal affiche le type de données et la taille, en octets, de chaque objet. Les valeurs d'index (par exemple, 0004) représentent les offsets d'octet pour les variables spécifiées.
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
Messages d'erreur
Certaines situations et exceptions peuvent provoquer l'enregistrement de messages d'erreur dans le fichier journal. Ces messages peuvent être particulièrement utiles lors de l'étude de problèmes qui impliquent l'interaction avec les composants natifs et DLL pour lesquels le code source natif n'est pas disponible. Vous pouvez utiliser les messages d'erreur pour vous aider avec les problèmes suivants :
Appels de fonction du code natif au code managé.
Appels à des interfaces COM du runtime. Une erreur HRESULT peut être retournée au code natif lorsqu'une fonction d'interface COM implémentée par le runtime est appelée. Il existe plusieurs interfaces implémentées par le runtime (notamment IUnknown, IDispatch, IConnectionPointContainer, IEnumConnectionPoints et IConnectionPoint), que le code natif peut appeler en utilisant un objet managé marshalé comme une interface COM. Lorsqu'un appel de fonction retourne une erreur au code natif dans l'une de ces interfaces, le runtime imprime un message d'erreur approprié avec l'erreur HRESULT et toute information pertinente supplémentaire.
Code natif qui doit utiliser des fonctionnalités qui ne sont pas prises en charge, par exemple IDispatch::GetTypeInfo.
Interfaces non implémentées. Le code natif peut recevoir une erreur E_NOINTERFACE de IUnknown::QueryInterface où il attend que l'objet COM managé ait implémenté une interface supplémentaire. Dans ce cas, le GUID de l'interface non implémentée est également fourni.
Exceptions managées. Elles peuvent se produire à l'intérieur de l'appel de fonction managé et provoquer son retour prématuré. Lors d'un appel COM, le runtime convertit l'exception en une valeur HRESULT d'échec qu'il retourne au code natif. Toutefois, si un rappel de délégué ou un appel COM n'attend pas de valeur de retour HRESULT, il n'existe aucune façon de garantir que le code natif reconnaît l'erreur et, par conséquent, un comportement inattendu peut se produire. Le journal d'interopérabilité contient un message d'erreur lorsqu'une exception survient pendant un appel de fonction d'interopérabilité du code natif au code managé. Ce message vous permet d'identifier les fonctions managées qui nécessitent une logique de gestion des erreurs supplémentaire pour bien fonctionner avec le code natif. Les facteurs suivants peuvent provoquer une exception managée :
L'utilisation de types dans votre définition d'interface COM ou signature DllImportAttribute qui ne sont pas pris en charge par le .NET Compact Framework provoquera une exception pendant le processus de compilation JIT. D'autres options sont souvent acceptables, par exemple l'utilisation d'un IntPtr.
Lorsque l'objet réel ne peut pas être forcé à correspondre au type spécifié dans la signature ou que les données d'objet ne peuvent pas être converties vers le type demandé, une exception est levée au moment de l'exécution lorsque la fonction est appelée. Cela se produit habituellement lors de la conversion d'un objet natif en un objet managé.
Il est difficile de déterminer ce qui provoque une exception lors de la création d'un wrapper RCW (Runtime Callable Wrapper) ou CCW (COM Callable Wrapper). Le fichier journal d'interopérabilité peut aider à déterminer la cause de ces problèmes lorsqu'un message d'erreur détaillé n'est pas fourni avec l'exception managée.
Différences avec le .NET Framework
Il existe des différences entre l'implémentation de l'interopérabilité COM dans le .NET Compact Framework et dans le .NET Framework complet. Le .NET Compact Framework ne prend pas en charge les éléments suivants :
Création d'un CCW qui contient une interface sans GUID spécifié.
Création d'un RCW pour une classe qui hérite d'une classe d'assembly d'interopérabilité.
Création d'un CCW qui contient une interface non générique avec une méthode générique.
Les wrappers RCW (Runtime Callable Wrappers) sont habituellement nettoyés lors de la finalisation, mais vous pouvez également utiliser la méthode ReleaseComObject ou FinalReleaseComObject pour libérer le wrapper RCW associé à un objet. Si vous utilisez ces options avancées pour gérer la durée de vie de vos objets et essayez d'utiliser l'objet une fois qu'il a été libéré pour effectuer un appel COM natif, une exception est levée et le fichier journal contient un message d'erreur relatif à la cause de l'exception.
Fichiers journaux de chargeur
Les fichiers journaux de chargeur se composent de deux sections : un en-tête et un corps. L'en-tête du fichier journal contient les données suivantes :
Nom du principal exécutable de l'application.
ID de processus tel qu'il a été assigné par le système d'exploitation.
Date et heure de création du fichier journal.
Version du .NET Compact Framework utilisée pour exécuter l'application.
Informations sur la plateforme sur laquelle votre application s'exécute.
Le corps du fichier journal inclut des informations de diagnostic sur chaque assembly chargé par votre application. Ces informations peuvent vous aider à localiser les erreurs rencontrées par le chargeur de classes au démarrage de l'application.
Le corps du fichier journal contient les données suivantes :
État de contrainte qui indique si votre application a été exécutée ou non en mode de compatibilité descendante.
Traçage pour chaque chargement de l'assembly, y compris l'emplacement à partir duquel l'assembly a été chargé et la version qui a été chargée.
Niveau de confiance assigné à chaque module lors du chargement.
Tout fichier de configuration associé à votre application.
Échec de la recherche des méthodes, types, assemblys et modules.
Échec de la recherche d'une DLL native ou d'une fonction pour un appel de code non managé.
Le tableau ci-dessous contient un exemple de fichier journal de chargeur. Les numéros de ligne sont approximatifs.
Numéro de ligne et description |
Entrée de journal |
---|---|
1 - Processus |
Process [\Program Files\VW\VW.exe] |
2 - ID de processus |
Process ID [0x4d9585d2] |
3 - Date |
Date [2005/02/25] |
4 - Heure |
Time [18:33:14] |
5 - Version du .NET Compact Framework |
NETCF [2.0.5035.00] |
6 - plateforme |
Platform [Windows CE v4.20.1081 (PocketPC) WinCE4ARMV4 release Beta2 ARMV4 IJITv2] |
7–14 - Opérations du Global Assembly Cache |
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 - Mode de compatibilité (0.0.0.0 indique l'absence du mode de compatibilité) |
Compatibility mode [0.0.0.0] |
16 - Chargement du module |
Loading module [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll] |
17 - Module chargé |
Loaded [mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969DB8053D3322AC] from [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll] |
Les deux dernières entrées (Chargement et Chargées) sont enregistrées pour chaque module. Les assemblys et leurs emplacements sont ainsi identifiés. Toutes les erreurs qui surviennent lors du chargement d'un module sont indiquées dans le journal de chargeur.
Exemples d'erreurs
Les deux exemples de cette section montrent comment vous pouvez utiliser le fichier journal de chargeur pour déterminer le moment où des erreurs sont rencontrées.
L'exemple suivant affiche les entrées de journal qui sont écrites lorsque le chargeur ne trouve pas un assembly.
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]
L'exemple suivant affiche les entrées de journal qui sont écrites lorsque le chargeur ne trouve pas un type spécifique.
Missing Type. Type [Cars.Jetta], Assembly [Cars].
Missing Type. Class [Cars.Jetta], Assembly [Cars, Version=5.0.0.0,
Culture=neutral, PublicKeyToken=null].
Voir aussi
Tâches
Comment : créer des fichiers journaux
Comment : configurer la version du runtime
Concepts
.Rubriques Comment relatives au .NET Compact Framework