Log File Information 

You can create log files that record actions for the following operations:

  • Interoperating with native code.

  • Loading programs.

  • Networking.

See How to: Create Log Files for instructions. This topic describes the output written to log files for interop and loader logging. Information about reading networking log files is not currently available.

Interop Log Files

The output for interop logging consists of the signatures of the interop function calls as they occur at run time, with any error messages.

Function Signatures

The signatures for both managed-to-native and native-to-managed calls are logged, and include the following types of calls:

  • Platform invoke calls.

  • COM vtable and Dispatch calls.

  • Delegate callbacks.

Interop logging can help you troubleshoot problems when calling or returning from an interop function call, such as when a parameter is not initialized as expected or when the program terminates unexpectedly.

The output for a function signature entry consists of three lines for each interop call. The first line represents flags identifying the type of function call made, and has one or more of the following elements:

  • [preservesig]
    The managed and native functions are assumed to have the same signature, with no translation from HRESULT to exception enforced by the runtime.
  • [delegate]
    Indicates that the function is a native-to-managed delegate callback. The delegate acts as a function pointer in native code.

The second line of the interop log file represents the managed signature. For managed-to-native function calls, this line identifies the managed function that calls the native code. For native-to-managed function calls, this line identifies the managed function that is being called from native code.

The third line represents the native signature, as expected by the runtime. This line identifies data types for each parameter and provides information about how the managed object data is marshaled. The runtime assumes the correct types are specified by the DllImportAttribute or in the COM interface signature definition. Failure to specify the correct types is a common error that can result in unexpected behavior because the function called is executed with incorrect parameter values.

Every type has a default marshaling type. Note that the marshaling behavior of a managed type can differ between COM calls and DllImportAttribute or delegate callback calls. You can use the MarshalAsAttribute attribute to specify a marshaling type other then the default. You must also use the ref keyword to identify parameters that are expected to be pointers in native code.

The following table shows interop logging of a platform invoke.

Line number and description Log entry

1 - Type of function call

[pinvokeimpl][preservesig]

2 - Managed signature

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

3 - Native signature

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

The following table shows interop logging of a delegate callback.


Line number and description Log entry

1 - Type of function call

[preservesig][delegate]

2 - Managed signature

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

3 - Native signature

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

The following table shows interop logging of a native-to-managed COM function call, where the runtime returns a failure HRESULT in the event of a managed exception.

Line number and description Log entry

1 - Type of function call

[no flags]

2 - Managed signature

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

3 - Native signature

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

Error Messages

Some situations and exceptions can cause error messages to be recorded in the log file. They can be especially useful when investigating issues that involve interoperating with native components and DLLs for which the native source code is not available. You can use error messages to help with the following issues:

  • Native-to-managed function calls.

  • Calling runtime COM interfaces. An HRESULT error can be returned to native code when a runtime-implemented COM interface function is called. There are several runtime-implemented interfaces, including IUnknown, IDispatch, IConnectionPointContainer, IEnumConnectionPoints, and IConnectionPoint, that native code can call into by using a managed object marshaled as a COM interface. When an error is returned to native code from a function call into one of these interfaces, the runtime prints out an appropriate error message giving the HRESULT and any additional relevant information.

  • Native code expecting to use functionality that is unsupported, such as IDispatch::GetTypeInfo.

  • Unimplemented interfaces. Native code may receive an E_NOINTERFACE error from IUnknown::QueryInterface where it expects the managed COM object to have implemented an additional interface. In this case, the GUID of the unimplemented interface is also provided.

  • Managed exceptions. Managed exceptions can occur inside the managed function call and cause it to return prematurely. When making a COM call, the runtime converts the exception into a failure HRESULT and returns this back to native code. However, for delegate callbacks and COM calls that do not expect HRESULT return values, there is no way to ensure native code is made aware of the error, and you may see unexpected behavior as a result. The interop log will contain an error message when an exception happens during a native-to-managed interop function call, helping you identify managed functions that need additional error-handling logic to work well with native code. The following factors can cause a managed exception.

    • Using types in your COM interface definition or DllImportAttribute signature that are not supported by the .NET Compact Framework will cause an exception to occur during the JIT compilation process. There are often alternative options that are acceptable, such as an IntPtr .

    • When either the actual object cannot be coerced to the type specified in the signature or the object data cannot be converted to the type requested, an exception is thrown at run time when the function is called. This usually occurs when converting a native object into a managed object.

    • Determining what causes an exception when creating a runtime callable wrapper (RCW) or a COM callable wrapper (CCW) is difficult. The interop log file can help determine the cause of these problems when a detailed error message is not provided with the managed exception.

Differences with the .NET Framework

There are differences between .NET Compact Framework implementation of COM interoperability and that of the full .NET Framework. The .NET Compact Framework does not support the following:

  • Creating a CCW (COM callable wrapper) containing an interface without a specified GUID.

  • Creating an RCW (runtime callable wrapper) for a class that inherits from an interop assembly class.

  • Creating a CCW containing a nongeneric interface with a generic method.

Runtime callable wrappers (RCWs) are usually cleaned up upon finalization, but you can also use the ReleaseComObject or FinalReleaseComObject method to release the RCW associated with an object. If you are using these advanced options to manage the lifetime of your objects and you attempt to use the object after it has been freed to make a native COM call, an exception is thrown and the log file contains an error message about the cause of the exception.

Loader Log Files

Loader log files consist of two sections: a header and a body. The header of the log file contains the following data:

  • Name of the application’s main executable.

  • Process ID as assigned by the operating system.

  • Date and time the log file was created.

  • Version of the .NET Compact Framework used to run the application.

  • Information about the platform on which your application is running.

The data in the body of the log file includes diagnostic information about each assembly as it is loaded by your application, which can help you find errors encountered by the class loader as your application starts.

The body of the log file contains the following data:

  • Coercion state, which indicates whether or not your application was run in backward compatibility mode.

  • Tracing for each assembly load, including where the assembly was loaded from and which version was loaded.

  • Trust level assigned to each module as it is loaded.

  • Any configuration files associated with your application.

  • Failures to find methods, types, assemblies, and modules.

  • Failures to find a native DLL or a function for a platform invoke call.

The following is an example of a loader log file. Line numbers are approximate.

Line number and description Log entry

1 - Process

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

2 - Process ID

Process ID [0x4d9585d2]

3 - Date

Date [2005/02/25]

4 - Time

Time [18:33:14]

5 - .NET Compact Framework version

NETCF [2.0.5035.00]

6 - Platform

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

7–14 - Global assembly cache operations

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 - Compatibility mode, indicates not in compatibility mode

Compatibility mode [0.0.0.0]

16 - Loading module

Loading module [\Windows\GAC_mscorlib_v2_0_0_0_cneutral_1.dll]

17 - Loaded module

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

Any errors from loading a module are indicated in the loader log.

Loading and Loaded entries are logged for each module. They identify the assemblies and their location.

Failure Examples

The following two examples show how you can use the loader log file to determine when errors are encountered. This first example shows the log entries that are written when the loader fails to find an 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]

This example shows the log entries that are written when the loader fails to find a specific type:

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

See Also

Tasks

How to: Create Log Files
How to: Configure Runtime Version

Concepts

.NET Compact Framework How-To Topics

Other Resources

Interoperability in the .NET Compact Framework
Performance and Diagnostics