我在WindowsCE .NET Compact Framework 3.5应用程序中使用OpenNetCF库。 问题是当我调用其中一个函数( NetworkInterface.GetAllNetworkInterfaces()是特定的)时,它会随机抛出无法捕获的异常并导致我的应用程序崩溃:
ExceptionCode: 0x80000002 exceptionAddress: 0x03F928C4 at NativeMethods.WZCDeleteIntfObj(INTF_ENTRY& Intf) at INTF_ENTRY.Dispose() at GetAllNetworkInterfaces()
我正在搜索网络,并在OpenNetCF社区的错误跟踪器中报告此错误。不幸的是,还没有人修复它,我很确定没有人会修复它。 我有源代码,所以我可能必须自己做。如果我能成功捕获异常而不会崩溃应用程序,我将很高兴。
抛出异常的方法实际上是以下列方式导入的本机方法:
//--------------------------------------- // 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);
如何从此方法中捕获异常?
答案 0 :(得分:1)
我在Windows紧凑框架中使用OpenNetCF
库时遇到了类似的问题。无法捕获的本机异常是随机抛出的,它使整个应用程序崩溃。在调查此问题的可能原因时,我可以了解它可能是由于内存泄漏导致系统内存不足或数据错位。
我调用GC.Collect()
来回收在调用OpenNETCF.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
方法之前无法访问的所有内存。
这解决了这个问题,之后我没有得到任何本机异常。
GC.Collect()
方法强制系统尝试回收最大可用内存量。所有对象,无论它们在记忆中存在多长时间,都被考虑收集;但是,不会收集托管代码中引用的对象。
答案 1 :(得分:0)
我倾向于将所有PInvoke调用设为私有,并将它们包装在执行异常捕获的公共方法中:
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
}
}
}
然后使用任何托管代码:
MyWrappingClass wrapper = new MyWrappingClass();
wrapper.useWZCDeleteIntfObj( Intf );
MyWrappingClass还可以作为一个方便的位置来放置帮助方法和方法,从而抽象出一些基础PInvoke调用,使得处理本机库变得更容易。
答案 2 :(得分:0)
尝试使用托管C ++将异常捕获为C ++ / C异常,然后重新抛出为CLR异常。当pInvoke变得太难时,托管C ++通常是一个不错的选择。
答案 3 :(得分:0)
我遇到了同样的问题。无法在c#try / catch中捕获NativeException。至少不在.NET CF 3.5上。
抛出的错误是DataType未对齐异常。这是一个可能发生在例如ARM处理器,因为ARM架构要求数据在内存中正确对齐。 我查看了OpenNetCF.Net代码,但找不到不对齐问题,也许我是Windows WZZ API中的一个错误导致错误。
我最终试图在C中捕获异常。本机异常是SEH异常。哪种是在C中实现异常的Windows方式 这意味着C ++ try / catch不会抓住它。 捕获它的方法是使用__try / __ except块。
所以我最终创建了一个C ++项目(下面的代码)。创建一个在wzcsapi.dll中调用WZCDeleteIntfObj的本机DLL。代码只是捕获并忽略异常。 然后我从codeplex中检索了OpenNet代码,并将其修改为使用我的原生dll作为wzcsapi的WZCDeleteIntfObj方法的包装器。 结果看起来很有希望,但我不知道这是否会导致内存泄漏。
<强> 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
来自OpenNetCF.Net的WZC.C的修改部分
//---------------------------------------
// 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);