I'm using OpenNetCF library in my WindowsCE .NET Compact Framework 3.5 application. The problem is that when I call one of its functions (NetworkInterface.GetAllNetworkInterfaces() to be specific), it randomly throws uncatchable exception and crashes my application:
ExceptionCode: 0x80000002 exceptionAddress: 0x03F928C4 at NativeMethods.WZCDeleteIntfObj(INTF_ENTRY& Intf) at INTF_ENTRY.Dispose() at GetAllNetworkInterfaces()
I've search the web and this bug is reported in bug tracer of the OpenNetCF community. Unfortunately, nobody has fixed it yet and I'm pretty sure that nobody is going to fix it. I've got the source code so probably I have to do it myself. I will be happy if I will managed to just catch the exception, without crashing the application.
The method that throws the exception is actually a native method imported in following way:
//--------------------------------------- // WZCDeleteIntfObj: cleans an INTF_ENTRY object that is // allocated within any RPC call. // // Parameters // pIntf // [in] pointer to the INTF_ENTRY object to delete [DllImport("wzcsapi.dll")] public static extern void WZCDeleteIntfObj( ref INTF_ENTRY Intf);
What can I do to catch the exception from this method?
I faced the similar problem while using the OpenNetCF
library in Windows compact framework. The uncatchable native exception was thrown randomly and it crashed the entire application. While investigating the probable causes for this issue, I could get to know that it could be due to memory leaks due to which the system would have ran out of memory or data misalignment.
I called GC.Collect()
to reclaim all memory that is inaccessible before calling OpenNETCF.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
method.
And this resolved the issue and I didn’t get any native exception thereafter.
GC.Collect()
method forces the system to try to reclaim the maximum amount of available memory. All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected.
I tend to make all PInvoke calls private, and wrap them in a public method which carries out the Exception catching:
class MyWrappingClass{
[DllImport("wzcsapi.dll")]
private static extern void WZCDeleteIntfObj(ref INTF_ENTRY Intf);
public void useWZCDeleteIntfObj(ref INTF_ENTRY Intf){ //you may wish to use a better method name
//you may wish to put some guards here, to check that Intf is valid before passing it to the native library.
try{
WZCDeleteIntfObj( Intf );
}catch(ExternalException e){ //try to catch more specific exception types, such as SEHException.
//handle the exception
}
}
}
Any managed code then uses:
MyWrappingClass wrapper = new MyWrappingClass();
wrapper.useWZCDeleteIntfObj( Intf );
MyWrappingClass also serves as a handy place to put helper methods and methods that abstract away some of the underlying PInvoke calls, making dealing with native libraries easier.
Try using managed C++ to catch the exception as a C++/C exception, and then rethrow as a CLR exception. When pInvoke gets too hard, managed C++ is often a good option.
I ran into the same problem. NativeException can not be caught in a c# try/catch. At least not on .NET CF 3.5.
The error thrown is a DataType unalignment exception. which is an error that can occur on e.g. ARM processors, because ARM architecture requires data to be aligned correctly in memory. I looked through the OpenNetCF.Net code, but could not find unalignment issues, maybee i is a bug in the Windows WZZ API causing the error.
I ended up trying to catch the exception in C. The native exception is a SEH exception. Which is the Windows way of implementing exceptions in C. This Means that C++ try/catch wont catch it. The way to catch it is with a __try/__except block.
So I ended up creating a C++ project (Code below). Creating a native DLL which calls WZCDeleteIntfObj in wzcsapi.dll. The code just catch and ignore the exception. Then i retrieved the OpenNet code from codeplex, and modified it to use my native dll as wrapper around wzcsapi's WZCDeleteIntfObj method. Results looks promising, i do however not know if this will cause a memory leak instead.
WZCWrapper.h
#include "stdafx.h"
#define WZCWrapper_API __declspec(dllexport)
typedef struct
{
DWORD dwDataLen;
LPBYTE pData;
} RAW_DATA, *PRAW_DATA;
typedef struct
{
LPWSTR wszGuid;
LPWSTR wszDescr;
ULONG ulMediaState;
ULONG ulMediaType;
ULONG ulPhysicalMediaType;
INT nInfraMode;
INT nAuthMode;
INT nWepStatus;
DWORD dwCtlFlags;
DWORD dwCapabilities;
RAW_DATA rdSSID;
RAW_DATA rdBSSID;
RAW_DATA rdBSSIDList;
RAW_DATA rdStSSIDList;
BOOL bInitialized;
} INTF_ENTRY, *PINTF_ENTRY;
WZCWrapper.dll
#include "stdafx.h"
#include "WZCWrapper.h"
typedef void (__cdecl *MYPROC)(PINTF_ENTRY);
static HINSTANCE wzcApiDll;
static BOOL initialized;
static MYPROC WZCDeleteIntfObj;
WZCWrapper_API VOID DLL_WZCDeleteIntfObj(PINTF_ENTRY pIntf) {
if (!initialized){
wzcApiDll = LoadLibrary(TEXT("wzcsapi.dll"));
WZCDeleteIntfObj = (MYPROC) GetProcAddress(wzcApiDll, TEXT("WZCDeleteIntfObj"));
initialized = TRUE;
}
__try
{
WZCDeleteIntfObj(pIntf);
}
__except (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) {
}
// FreeLibrary(wzcApiDll); // will release dll (we should not use this, keeping the dll open, as we need it again
}
WZCWrapper.def
LIBRARY "WZCWrapper"
EXPORTS
WZCDeleteIntfObj=DLL_WZCDeleteIntfObj
Modified Part of WZC.C from OpenNetCF.Net
//---------------------------------------
// WZCDeleteIntfObj: cleans an INTF_ENTRY object that is
// allocated within any RPC call.
//
// Parameters
// pIntf
// [in] pointer to the INTF_ENTRY object to delete
[DllImport("WZCWrapper.dll")]
internal static extern void
WZCDeleteIntfObj(
ref INTF_ENTRY Intf);
User contributions licensed under CC BY-SA 3.0