2
在桌面Windows中,我可以使用windows.h
中的SetUnhandledExceptionFilter
函數,但它在WinCE中不起作用。我如何在WinCE中捕獲未處理的異常?如何在WinCE中捕捉未處理的異常?
注意:我使用C++而不是.NET。
在桌面Windows中,我可以使用windows.h
中的SetUnhandledExceptionFilter
函數,但它在WinCE中不起作用。我如何在WinCE中捕獲未處理的異常?如何在WinCE中捕捉未處理的異常?
注意:我使用C++而不是.NET。
我到目前爲止發現的唯一辦法是包裝每一個線程的執行與應用:
__try
{
// Call the thread start function here
}
__except(MyExceptionFilter(GetExceptionInformation())
{
// Handle the exception here
}
這聽起來像一個大量的工作,但如果你寫一個由相對容易函數封裝了線程你是這樣的:
typedef struct {
void* startFct;
void* args;
} ThreadHookArgs;
// "params" contains an heap-allocated instance of ThreadHookArgs
// with the wrapped thread start function and its arguments.
DWORD WINAPI wrapThread(LPVOID params) {
ThreadHookArgs threadParams;
memcpy(&args, params, sizeof(ThreadHookArgs));
// Delete the parameters, now we have a copy of them
delete params;
__try {
// Execute the thread start function
return ((LPTHREAD_START_ROUTINE) threadParams.startFct) (threadParams.args);
}
__except(MyExceptionFilter(GetExceptionInformation())
{
// Handle the exception here
return EXIT_FAILURE;
}
}
然後編寫調用掛鉤,而不是線程啓動功能自己線程創建函數:
// Drop-in replacement for CreateThread(), executes the given
// start function in a SEH exception handler
HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId)
{
HANDLE hThread;
DWORD dwThreadId;
LPTHREAD_START_ROUTINE startFct = lpStartAddress;
LPVOID startParam = lpParameter;
// Allocate the hook function arguments on the heap.
// The function will delete them when it runs.
ThreadHookArgs* hookArgs = new ThreadHookArgs;
hookArgs->fct = lpStartAddress;
hookArgs->args = lpParameter;
// Set the start function of the created thread to
// our exception handler hook function
startFct = (LPTHREAD_START_ROUTINE) &wrapThread;
startParam = hookArgs;
// Start the hook function, which will in turn execute
// the desired thread start function
hThread = CreateThread(lpThreadAttributes,
dwStackSize,
startFct,
startParam,
dwCreationFlags,
&dwThreadId);
return hThread;
}
請注意,如果您使用的是Windows CE 6.0及更高版本,這些版本的向量異常處理,這可能使它更容易:
http://msdn.microsoft.com/en-us/library/ee488606%28v=winembedded.60%29.aspx
向量異常處理不解決這個問題,因爲向量在調用任何幀特定的過濾器之前調用異常過濾器,而在調用所有異常過濾器之後調用未處理的異常過濾器。這是非常容易出錯的,因爲它使許多假設在其他假設之前被調用。 –
此解決方案的另一個問題。如果您完全不尊重Windows CE ABI,那麼可能會跳過基於幀的異常過濾器,因爲內核可能無法正確展開堆棧。請注意,即使程序不尊重Windows CE ABI,矢量異常過濾器仍然會被調用。 –
好點。事實上,我只使用向量化異常處理來捕獲STATUS_CRASH_DUMP,並繞過在這種情況下得到的錯誤窗口,而是傾倒關於觸發它的異常的日誌;我也沒有意識到ABI問題,迄今爲止解決方案工作得很好。可悲的是,似乎沒有真正普遍的辦法來解決這個問題。 –