我正在嘗試編寫一個可以加載託管插件的插件系統。如果有任何例外,主機應該能夠卸載插件。 我POC我在C#中拋出這樣一個異常的示例代碼庫...託管clr和捕捉線程異常
public static int StartUp(string arguments)
{
Console.WriteLine("Started exception thrower with args {0}", arguments);
Thread workerThread = new Thread(() =>
{
Console.WriteLine("Starting a thread, doing some important work");
Thread.Sleep(1000);
throw new ApplicationException();
}
);
workerThread.Start();
workerThread.Join();
Console.WriteLine("this should never print");
return 11;
}
然後我有本地的Win32控制檯應用程序,這樣的..
int _tmain(int argc, _TCHAR* argv[])
{
ICLRMetaHost *pMetaHost = NULL;
HRESULT hr;
ICLRRuntimeInfo *runtimeInfo = NULL;
__try
{
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
hr = pMetaHost->GetRuntime(L"v4.0.30319",IID_ICLRRuntimeInfo,(LPVOID*)&runtimeInfo);
ICLRRuntimeHost *runtimeHost = NULL;
hr = runtimeInfo->GetInterface(CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost);
ICLRControl* clrControl = NULL;
hr = runtimeHost->GetCLRControl(&clrControl);
ICLRPolicyManager *clrPolicyManager = NULL;
clrControl->GetCLRManager(IID_ICLRPolicyManager, (LPVOID*)&clrPolicyManager);
clrPolicyManager->SetDefaultAction(OPR_ThreadAbort,eUnloadAppDomain);
hr = runtimeHost->Start();
DWORD returnVal = NULL;
hr = runtimeHost->ExecuteInDefaultAppDomain(L"ExceptionThrower.dll",L"ExceptionThrower.MainExceptionThrower",L"StartUp",L"test",&returnVal);
runtimeHost->Release();
}
__except(1)
{
wprintf(L"\n Error thrown %d",e);
}
return 0;
}
問題是,如果我使用上面的代碼,主機將完成運行託管代碼(「永不打印」這行將最終打印) 如果我刪除了clrPolicyManager-> SetUnhandledExceptionPolicy(eHostDeterminedPolicy),則主機進程將崩潰。
任何事情都可以在非託管主機上完成,它可以從運行時中正常刪除錯誤的應用程序,並繼續工作?
您的代碼啓用了.NET 1.x異常處理策略。這只是終止線程。不是你想要的,你還需要調用ICLRPolicyManager :: SetDefaultAction()來告訴它在線程中止時卸載應用程序域。你仍然有一個死線程,使用__try/__ catch來捕捉異常。 –
我添加了以下行clrPolicyManager-> SetDefaultAction(OPR_ThreadAbort,eUnloadAppDomain);到代碼,我已經更新了代碼,但效果是一樣的,主機進程仍然崩潰 –
您可能錯過了評論的「死線程」部分。你必須抓住SEH異常。異常代碼是0xe0434f4d。 http://msdn.microsoft.com/en-us/library/s58ftw19%28v=VS.100%29.aspx –