(throwing) . C++ , API- - :
// throw an exception // HRESULT SetErrorInfo([in] ULONG reserved, // m.b.z. [in] IErrorlnfo *pei); // catch an exception // HRESULT GetErrorInfo([in] ULONG reserved, // m.b.z. [out] IErrorInfo **ppei);
SetErrorInfo , (logical thread)1. GetErrorInfo , GetErrorInfo S_FALSE, , . , IErrorInfo:
[ object, uuid(1CF2B120-547D-101B-8E65-08002B2BD119) ] interface IErrorInfo: IUnknown { // get IID of interface that threw exception // IID , HRESULT GetGUID([out] GUID * pGUID); // get class name of object that threw exception // , HRESULT GetSource([out] BSTR * pBstrSource); // get human-readable description of exception // HRESULT GetDescription([out] BSTR * pBstrDescription); // get WinHelp filename of documentation of error // WinHelp, HRESULT GetHelpFile([out] BSTR * pBstrHelpFile); // get WinHelp context ID for documentation of error // WinHelp HRESULT GetHelpContext([out] DWORD * pdwHelpContext); }
IErrorInfo.
IErrorInfo, API- CreateErrorInfo:
HRESULT CreateErrorInfo([out] ICreateErrorInfo **ppcei);
IErrorInfo ICreateErrorInfo, :
[ object, uuid(22F03340-547D-101B-8E65-08002B2BD119) ] interface ICreateErrorInfo: IUnknown { // set IID of interface that threw exception // IID , HRESULT SetGUID([in] REFGUID rGUID); // set class name of object that threw exception // , HRESULT SetSource([in, string] OLECHAR* pwszSource); // set human-readable description of exception // HRESULT SetDescription([in, string] OLECHAR* pwszDesc); // set WinHelp filename of documentation of error // WinHelp, HRESULT SetHelpFile([in, string] OLECHAR* pwszHelpFile); // set WinHelp context ID for documentation of error // WinHelp HRESULT SetHelpContext([in] DWORD dwHelpContext); }
, , IErrorInfo.
- , :
STDMETHODIMP PugCat::Snore(void) { if (this->IsAsleep()) // ok to perform operation? // ? return this->DoSnore(); //do operation and return // //otherwise create an exception object // ICreateErrorInfo * i = 0; HRESULT hr = CreateErrorInfo(&pcei); assert(SUCCEEDED(hr)); // initialize the exception object // hr = pcei->SetGUID(IID_IPug); assert(SUCCEEDED(hr)); hr = pcei->SetSource(OLESTR("PugCat")); assert(SUCCEEDED(hr)); hr = pcei->SetDescription(OLESTR("I am not asleep!")); assert(SUCCEEDED(hr)); hr = pcei->SetHelpFile(OLESTR("C:\\PugCat.hlp")); assert(SUCCEEDED(hr)); hr = pcei->SetHelpContext(5221); assert(SUCCEEDED(hr)); // "throw" exception // " " IErrorInfo *pei = 0; hr = pcei->QueryInterface(IID_IErrorInfo, (void**)&pei); assert(SUCCEEDED(hr)); hr = SetErrorInfo(0, pei); // release resources and return a SEVERITY_ERROR result // // SEVERITY_ERROR ( ) pei->Release(); pcei->Release(); return PUG_E_PUGNOTASLEEP; }
, SetErrorInfo, , " " , GetErrorInfo.
, , ISupportErrorInfo, , . , , GetErrorInfo2. :
[ object, uuid(DFOB3060-548F-101B-8E65-08002B2BD119) ] interface ISupportErrorInfo: IUnknown { HRESULT InterfaceSupportsErrorInfo([in] REFIID riid); }
, PugCat, , . :
STDMETHODIMP PugCat::InterfaceSupportsErrorInfo(REFIID riid) { if (riid == IID_IAnimal || riid == IID_ICat || riid == IID_IDog || riid == IID_IPug) return S_OK; else return S_FALSE; }
, , ISupportErrorInfo GetErrorInfo:
void TellPugToSnore(/*[in]*/ IPug *pPug) { // call a method // HRESULT hr = pPug->Snore(); if (FAILED(hr)) { // check to see if object supports exceptions // , ISupportErrorInfo *psei = 0; HRESULT hr2 =pPug->QueryInterface( IID_ISupportErrorInfo, (void**)&psei); if (SUCCEEDED(hr2)) { // check if object supports exceptions via IPug methods // , IPug hr2 = psei->InterfaceSupportsErrorInfo(IID_IPug); if (hr2 == S_OK) { // read exception object for this logical thread // IErrorInfo * i = 0; hr2 = GetErrorInfo(0, &pei); if (hr2 == S_OK) { // scrape out source and description strings // BSTR bstrSource = 0, bstrDesc = 0; hr2 = pei->GetDescription(&bstrDesc); assert(SUCCEEDED(hr2)); hr2 = pei->GetSource(&bstrSource); assert(SUCCEEDED(hr2)); // display error information to end-user // MessageBoxW(0, bstrDesc ? bstrDesc : L"", bstrSource ? bstrSource : L"", MB_OK); // free resources // SysFreeString(bstrSource); SysFreeString(bstrDesc); pei->Release(); } } psei->Release(); } } if (hr2 != S_OK) // something went wrong with exception // - MessageBox(0, "Snore Failed", "IPug", MB_OK); }
C++, . , HRESULT C++:
struct COMException { HRESULT m_hresult; // hresult to return // hresult IErrorInfo *m_pei; // exception to throw // COMException(HRESULT hresult, REFIID riid, const OLECHAR *pszSource, const OLECHAR *pszDesc, const OLECHAR *pszHelpFile = 0, DWORD dwHelpContext = 0) { // create and init an error info object // ICreateErrorInfo * i = 0; HRESULT hr = CreateErrorInfo(&pcei); assert(SUCCEEDED(hr)); hr = pcei->SetGUID(riid); assert(SUCCEEDED(hr)); if (pszSource) hr=pcei->SetSource(const_cast<OLECHAR*>(pszSource)); assert(SUCCEEDED(hr)); if (pszDesc) hr=pcei->SetDescription(const_cast<OLECHAR*>(pszDesc)); assert(SUCCEEDED(hr)); if (pszHelpFile) hr=pcei->SetHelpFile(const_cast<OLECHAR*>(pszHelpFile)); assert(SUCCEEDED(hr)); hr = pcei->SetHelpContext(dwHelpContext); assert(SUCCEEDED(hr)); // hold the HRESULT and IErrorInfo ptr as data members // HRESULT IErrorInfo m_hresult = hresult; hr=pcei->QueryInterface(IID_IErrorInfo, (void**)&m_pei); assert(SUCCEEDED(hr)); pcei->Release(); } };
++- COMException Snore , C++ :
STDMETHODIMP PugCat::Snore(void) { HRESULT hrex = S_OK; try { if (this->IsAsleep()) return this->DoSnore(); else throw COMException(PUG_E_PUGNOTASLEEP, IID_IPug, OLESTR("PugCat"), OLESTR("I am not asleep!")); } catch (COMException& ce) { // a C++ COMException was thrown // COMException C++ HRESULT hr = SetErrorInfo(0, ce.m_pei); assert(SUCCEEDED(hr)); ce.m_pei->Release(); hrex = ce.m_hresult; } catch (...) { // some unidentified C++ exception was thrown // - C++ COMException ex(E_FAIL, IID_IPug, OLESTR("PugCat"), OLESTR("A C++ exception was thrown")); HRESULT hr = SetErrorInfo(0, ex.m_pei); assert(SUCCEEDED(hr)); ex.m_pei->Release(); hrex = ex.m_hresult; } return hrex; }
, , ++- . .
1 (logical thread) , OS- .
2 , GetErrorInfo, , , , .