Informazioni sui file di log

Aggiornamento: novembre 2007

È possibile creare file di log nei quali registrare le azioni relative alle operazioni seguenti:

  • Interoperabilità con codice nativo.

  • Caricamento di programmi.

  • Rete.

Per informazioni sulle chiavi del Registro di sistema che controllano la registrazione e su come generare file di log, vedere Procedura: creare file di log.

In questo argomento viene descritto l'output scritto nei file di log per la registrazione delle azioni relative all'interoperabilità e al caricatore.

File di log di interoperabilità

L'output per la registrazione delle operazioni relative all'interoperabilità è costituito dalle firme delle chiamate di funzioni di interoperabilità in fase di esecuzione, con eventuali messaggi di errore.

In .NET Compact Framework versione 3.5 è stato migliorato il supporto per la registrazione delle operazioni relative all'interoperabilità, descritto nella sezione "Marshalling completo" più avanti in questo argomento.

Firme di funzione

Vengono registrate le firme per le chiamate gestite a codice nativo e le chiamate native a codice gestito dei tipi seguenti:

  • Chiamate di richiamo piattaforma.

  • Chiamate COM vtable e Dispatch.

  • Callback di delegato.

La registrazione delle operazioni relative all'interoperabilità consente di risolvere i problemi relativi all'esecuzione o alla restituzione di chiamate di funzioni di interoperabilità, ad esempio la mancata inizializzazione di un parametro come previsto o la terminazione imprevista di un programma.

L'output per una voce di firma di funzione è costituito da tre righe per ogni chiamata di interoperabilità. La prima riga fornisce flag che identificano il tipo di chiamata di funzione effettuata e include uno o più dei seguenti elementi:

  • [pinvokeimpl]
    Identifica una chiamata da codice gestito a codice nativo in cui vene utilizzato l'attributo DllImportAttribute.

  • [Ctor]
    Identifica un costruttore per una classe assembly di interoperabilità generato dall'Utilità di importazione della libreria dei tipi (Tlbimp.exe).

  • [preservesig]
    Si presuppone che le firme delle funzioni native e gestite siano uguali, senza conversione da HRESULT all'eccezione applicata dal runtime.

  • [delegate]
    Indica se la funzione è un callback di delegato nativo a codice gestito. Il delegato funge da puntatore alla funzione in codice nativo.

La seconda riga del file di log di interoperabilità rappresenta la firma gestita. Per le chiamate di funzione gestite a codice nativo questa riga identifica la funzione gestita che chiama il codice nativo. Per le chiamate di funzione native a codice gestito questa riga identifica la funzione gestita chiamata dal codice nativo.

La terza riga rappresenta la firma nativa, come previsto dal runtime. Questa riga identifica i tipi di dati per ogni parametro e contiene informazioni su come effettuare il marshalling dei dati di oggetti gestiti. Dal runtime viene previsto che i tipi corretti siano specificati dall'attributo DllImportAttribute o nella definizione della firma dell'interfaccia COM. L'impossibilità di specificare i tipi corretti è un errore comune che può causare un comportamento imprevisto, poiché la funzione viene eseguita con valori di parametri non corretti.

Per ogni tipo esiste un tipo di marshalling predefinito. Il comportamento di marshalling di un tipo gestito può essere diverso a seconda che si utilizzino chiamate COM o l'attributo DllImportAttribute oppure chiamate di callback del delegato. È possibile utilizzare l'attributo MarshalAsAttribute per specificare un tipo di marshalling diverso da quello predefinito. È necessario inoltre utilizzare la parola chiave ref per identificare i parametri che rappresentano un puntatore a un tipo di valore o un puntatore a un puntatore, per un tipo di riferimento.

Nella tabella seguente è visualizzata la registrazione delle operazioni relative all'interoperabilità di un richiamo piattaforma.

Numero di riga e descrizione

Voce del log

1 - Tipo di chiamata di funzione

[pinvokeimpl][preservesig]

2 - Firma gestita

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

3 - Firma nativa

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

Nella tabella seguente è visualizzata la registrazione delle operazioni relative all'interoperabilità di callback di un delegato.

Numero di riga e descrizione

Voce del log

1 - Tipo di chiamata di funzione

[preservesig][delegate]

2 - Firma gestita

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

3 - Firma nativa

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

Nella tabella riportata di seguito viene illustrata la registrazione delle operazioni relative all'interoperabilità di una chiamata di funzione COM da codice nativo a codice gestito, dove il runtime restituisce un errore HRESULT in caso di un'eccezione gestita.

Numero di riga e descrizione

Voce del log

1 - Tipo di chiamata di funzione

Nessun flag

2 - Firma gestita

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

3 - Firma nativa

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

Marshalling completo

In .NET Compact Framework versione 3.5 è inoltre supportato il marshalling completo per la registrazione delle operazioni relative all'interoperabilità. Nel marshalling completo vengono registrate le informazioni su oggetti sottoposti a marshalling contenuti in strutture o in tipi di riferimento.

Nell'output del log seguente viene illustrato un esempio di una chiamata pInvoke che utilizza oggetti sottoposti a marshalling contenuti in una struttura. Nella prima riga della sezione del marshalling completo viene specificato il motivo per cui è stato chiamato il gestore di marshalling completo. In questo esempio è stato chiamato per calcolare la dimensione della struttura. Nel log è indicato il tipo di dati e la dimensione, in byte, di ogni oggetto. I valori di indice, ad esempio 0004, rappresentano gli offset dei byte per le variabili specificate.

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

Messaggi di errore

Alcune situazioni ed eccezioni possono causare la registrazione nel file di log di messaggi di errore, che possono essere particolarmente utili quando si analizzano problemi riguardanti l'interoperabilità con componenti nativi e DLL per i quali non è disponibile il codice sorgente nativo. È possibile utilizzare i messaggi di errore per la risoluzione dei seguenti problemi:

  • Chiamate di funzione native a codice gestito.

  • Chiamate di interfacce COM di runtime. Un errore HRESULT può essere restituito al codice nativo quando viene chiamata una funzione dell'interfaccia COM implementata dal runtime. Sono disponibili diverse interfacce implementate dal runtime, tra cui IUnknown, IDispatch, IConnectionPointContainer, IEnumConnectionPoints e IConnectionPoint, che possono essere chiamate dal codice nativo utilizzando un oggetto gestito per il quale è stato effettuato il marshalling come interfaccia COM. Quando al codice nativo viene restituito un errore da una chiamata di funzione in una di queste interfacce, dal runtime viene visualizzato un messaggio di errore appropriato contenente il valore HRESULT ed eventuali altre informazioni rilevanti.

  • Codice nativo dal quale è previsto l'utilizzo di funzionalità non supportate, come IDispatch::GetTypeInfo.

  • Interfacce non implementate Il codice nativo può ricevere un errore E_NOINTERFACE da IUnknown::QueryInterface, dove si prevedeva l'implementazione di un'interfaccia aggiuntiva da parte dell'oggetto COM gestito. In questo caso viene fornito anche il GUID dell'interfaccia non implementata.

  • Eccezioni gestite. Le eccezioni gestite possono verificarsi all'interno della chiamata di funzione gestita e determinarne la restituzione anticipata. Quando si effettua una chiamata COM, l'eccezione viene convertita dal runtime in un errore HRESULT che viene restituito al codice nativo. Se tuttavia un callback di delegato o una chiamata COM non prevede un valore restituito HRESULT, non è possibile accertarsi che venga rilevato l'errore, e di conseguenza potrebbero verificarsi comportamenti imprevisti. Nel log di interoperabilità verrà visualizzato un messaggio di errore quando si verifica un'eccezione durante una chiamata di funzione di interoperabilità da codice nativo a codice gestito. Questo messaggio consentirà di identificare le funzioni gestite che richiedono una logica di gestione degli errori aggiuntiva per il funzionamento corretto del codice nativo. Le seguenti condizioni possono causare un'eccezione gestita:

    • L'utilizzo nella definizione dell'interfaccia COM o della firma DllImportAttribute di tipi non supportati in .NET Compact Framework causerà un'eccezione durante il processo di compilazione JIT. Sono spesso disponibili opzioni alternative accettabili, ad esempio una struttura IntPtr.

    • Quando l'oggetto effettivo non può essere assegnato al tipo specificato nella firma oppure i dati dell'oggetto non possono essere convertiti nel tipo richiesto, viene generata un'eccezione in fase di esecuzione quando viene chiamata la funzione. Ciò si verifica solitamente quando si converte un oggetto nativo in un oggetto gestito.

    • Non è semplice determinare la causa di un'eccezione quando si crea un RCW (Runtime Callable Wrapper) o un CCW (COM Callable Wrapper). Il file di log di interoperabilità può consentire di determinare la causa di questi problemi quando non è disponibile un messaggio di errore dettagliato con l'eccezione gestita.

Differenze rispetto a .NET Framework

Esistono differenze tra l'implementazione dell'interoperabilità COM in .NET Compact Framework e nella versione completa di .NET Framework. In .NET Compact Framework non viene supportato quanto riportato di seguito:

  • Creazione di un CCW che contiene un'interfaccia senza un GUID specificato.

  • Creazione di un RCW per una classe che eredita da una classe assembly di interoperabilità.

  • Creazione di un CCW che contiene un'interfaccia non generica con un metodo generico.

Gli RCW vengono generalmente liberati al completamento, ma è anche possibile utilizzare il metodo ReleaseComObject o FinalReleaseComObject per rilasciare l'RCW associato a un oggetto. Se si utilizzano queste opzioni avanzate per gestire la durata degli oggetti e si tenta di utilizzare l'oggetto dopo che è stato liberato per effettuare una chiamata COM nativa, verrà generata un'eccezione e nel file di log verrà visualizzato un messaggio di errore relativo alla causa dell'eccezione.

File di log del caricatore

I file di log del caricatore sono composti da due sezioni, ovvero un'intestazione e un corpo. Nell'intestazione del file di log sono contenuti i seguenti dati:

  • Nome dell'eseguibile principale dell'applicazione.

  • ID processo assegnato dal sistema operativo.

  • Data e ora di creazione del file di log.

  • Versione di .NET Compact Framework utilizzata per eseguire l'applicazione.

  • Informazioni sulla piattaforma sulla quale è in esecuzione l'applicazione.

Nel corpo del file di log sono presenti le informazioni diagnostiche su ogni assembly caricato dall'applicazione, che consentono di individuare gli errori che si verificano nel caricatore di classe all'avvio dell'applicazione.

Nel corpo del file di log sono contenuti i seguenti dati:

  • Stato di coercizione che indica se l'applicazione è stata eseguita in modalità di compatibilità con le versioni precedenti.

  • Analisi per ogni assembly caricato, comprese informazioni riguardanti il punto da dove è stato caricato l'assembly e quale versione è stata caricata.

  • Livello di attendibilità assegnato a ogni modulo al caricamento.

  • Qualsiasi file di configurazione associato all'applicazione.

  • Impossibilità di trovare metodi, tipi, assembly e moduli.

  • Impossibilità di trovare una DLL nativa o una funzione per una chiamata pInvoke.

Nella tabella riportata di seguito viene illustrato un esempio del file di log di un caricatore. I numeri di riga sono approssimativi.

Numero di riga e descrizione

Voce del log

1 - Processo

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

2 - ID processo

Process ID [0x4d9585d2]

3 - Data

Date [2005/02/25]

4 - Ora

Time [18:33:14]

5 - Versione di .NET Compact Framework

NETCF [2.0.5035.00]

6 - Piattaforma

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

7–14 - Operazioni relative alla 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 - Modalità di compatibilità, 0.0.0.0 indica non in modalità di compatibilità

Compatibility mode [0.0.0.0]

16 - Modulo in fase di caricamento

Loading module [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll]

17 - Modulo caricato

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

Le ultime due voci (Modulo in fase di caricamento e Modulo caricato) vengono registrate per ogni modulo. Consentono di identificare gli assembly e i relativi percorsi. Nel log del caricatore viene indicato qualsiasi errore relativo al caricamento di un modulo.

Esempi di errori

Nei due esempi riportati nella presente sezione viene illustrato come utilizzare il file di log del caricatore per determinare quando si verificano errori.

Nell'esempio seguente vengono illustrate le voci del log scritte quando il caricatore non è in grado di trovare 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]

Nell'esempio seguente vengono illustrate le voci del log scritte quando il caricatore non è in grado di trovare un tipo specifico.

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

Vedere anche

Attività

Procedura: creare file di log

Procedura: configurare la versione runtime

Concetti

Procedure relative a .NET Compact Framework

Altre risorse

Interoperabilità in .NET Compact Framework

Prestazioni e diagnostica in .NET Compact Framework