Sub UseCollie(fido as ICollie)
fido.HairCount = fido.HairCount β (fido.Age * 1000)
fido.CurrentThought = Β«I wish I had a boneΒ»
End Sub
Π‘++-ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΡΡΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° ΠΏΡΠΎΡΡΠΎ ΠΏΡΠΈΠ±Π°Π²Π»ΡΠ΅Ρ ΠΊ ΠΈΠΌΠ΅Π½Π°ΠΌ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ put ΠΈΠ»ΠΈ get, ΡΡΠΎΠ±Ρ ΠΏΠΎΠ΄ΡΠΊΠ°Π·Π°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΡΡ, ΡΡΠΎ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΠ΅ ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΊ ΡΠ²ΠΎΠΉΡΡΠ²Ρ:
void UseCollie(ICollie *pFido)
{
long n1, n2;
HRESULT hr = pFido->getHairCount(&n1);
assert(SUCCEEDED(hr));
hr = pFido->getAge(&n2);
assert(SUCCEEDED(hr));
hr = pFido->putHairCount(n1 β (n2 * 1000)): assert(SUCCEEDED(hr));
BSTR bstr = SysAllocString(OLESTR(Β«I wish I had a boneΒ»));
hr = pFido->putCurrentThought(bstr);
assert(SUCCEEDED(hr));
SysFreeString(bstr);
}
Π₯ΠΎΡΡ ΡΠ²ΠΎΠΉΡΡΠ²Π° Π½Π°ΠΏΡΡΠΌΡΡ Π½Π΅ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°ΡΡ ΡΠ°Π·Π²ΠΈΡΠΈΡ, ΠΎΠ½ΠΈ ΠΏΠΎΠ»Π΅Π·Π½Ρ Π΄Π»Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠΎΡΠ½ΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠΉ Π½Π° ΡΠ΅ ΡΠ·ΡΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ[1].
ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
Π‘ΠΠ ΠΈΠΌΠ΅Π΅Ρ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ Π²ΡΠ±ΡΠ°ΡΡΠ²Π°Π½ΠΈΡ (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 Π²ΠΎΠ·Π²ΡΠ°ΡΡΡ SFALSE, ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Ρ ΡΠ΅ΠΌ ΡΠ°ΠΌΡΠΌ, ΡΡΠΎ Π½Π΅ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ Π½Π΅Ρ. ΠΠ°ΠΊ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΈΠ· ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΡ Π½ΠΈΠΆΠ΅ ΠΏΠΎΠ΄ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ, ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΠΏΠΎ ΠΊΡΠ°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ 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(IIDIPug);
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(IIDIErrorInfo, (void**)&pei);
assert(SUCCEEDED(hr));
hr = SetErrorInfo(0, pei);
// release resources and return a SEVERITYERROR result
// Π²ΡΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅ΠΌ ΡΠ΅ΡΡΡΡΡ ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ
// SEVERITYERROR (ΡΠ΅ΡΡΠ΅Π·Π½ΠΎΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ)
pei->Release();
pcei->Release();
return PUGEPUGNOTASLEEP;
}
ΠΡΠΌΠ΅ΡΠΈΠΌ, ΡΡΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ Π² ΠΏΡΠΎΡΠ΅Π΄ΡΡΡ SetErrorInfo, Π‘ΠΠ ΡΠΎΡ ΡΠ°Π½ΡΠ΅Ρ ΡΡΡΠ»ΠΊΡ Π½Π° ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π΄ΠΎ ΡΠ΅Ρ ΠΏΠΎΡ, ΠΏΠΎΠΊΠ° ΠΎΠ½ΠΎ Π½Π΅ Π±ΡΠ΄Π΅Ρ Β«ΠΏΠ΅ΡΠ΅Ρ Π²Π°ΡΠ΅Π½ΠΎΒ» Π²ΡΠ·ΡΠ²Π°ΡΡΠΈΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΠΌ GetErrorInfo.
ΠΠ±ΡΠ΅ΠΊΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ±ΡΠ°ΡΡΠ²Π°ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π‘ΠΠ, Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ISupportErrorInfo , ΡΡΠΎΠ±Ρ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ. ΠΡΠΎΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ, ΡΡΠΎΠ±Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ, Π²Π΅ΡΠ½ΡΠΉ Π»ΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π΄Π°Π΅Ρ GetErrorInfo[2]. ΠΡΠΎΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΏΡΠ΅Π΄Π΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡ:
[ object, uuid(DFOB3060-548F-101B-8E65-08002B2BD119) ]
interface ISupportErrorInfo: IUnknown
{
HRESULT InterfaceSupportsErrorInfo([in] REFIID riid);
}
ΠΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΡΠΎ ΠΊΠ»Π°ΡΡ PugCat, ΡΠ°ΡΡΠΌΠΎΡΡΠ΅Π½Π½ΡΠΉ Π² ΡΡΠΎΠΉ Π³Π»Π°Π²Π΅, ΡΠ±ΡΠ°ΡΡΠ²Π°Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΈΠ· ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΈΠΌ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°. Π’ΠΎΠ³Π΄Π° Π΅Π³ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π±ΡΠ΄Π΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ°ΠΊ:
STDMETHODIMP PugCat::InterfaceSupportsErrorInfo(REFIID riid)
{
if (riid == IIDIAnimal || riid == IIDICat || riid == IIDIDog || riid == IIDIPug) return SOK;
else return SFALSE;
}
ΠΠΈΠΆΠ΅ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ ΠΏΡΠΈΠΌΠ΅Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ Π½Π°Π΄Π΅ΠΆΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ 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( IIDISupportErrorInfo, (void**)&psei);
if (SUCCEEDED(hr2))
{
// check if object supports Π‘ΠΠ exceptions via IPug methods
// ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π»ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π‘ΠΠ ΡΠ΅ΡΠ΅Π· ΠΌΠ΅ΡΠΎΠ΄Ρ
IPug hr2 = psei->InterfaceSupportsErrorInfo(IIDIPug);
if (hr2 == SOK)
{
// read exception object for this logical thread
// ΡΠΈΡΠ°Π΅ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΡΠΎΠΊΠ°
IErrorInfo *ΡΠ΅i = 0;
hr2 = GetErrorInfo(0, &pei);
if (hr2 == SOK)
{
// 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Β»", MBOK);
// free resources
// Π²ΡΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅ΠΌ ΡΠ΅ΡΡΡΡΡ
SysFreeString(bstrSource);
SysFreeString(bstrDesc);
pei->Release();
}
}
psei->Release();
}
}
if (hr2!= SOK)
// something went wrong with exception
// ΡΡΠΎ-ΡΠΎ Π½Π΅Π»Π°Π΄Π½ΠΎ Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ΠΌ
MessageBox(0, Β«Snore FailedΒ», Β«IPugΒ», MBOK);
}
ΠΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠΎ ΠΎΡΠΎΠ±ΡΠ°Π·ΠΈΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π‘ΠΠ Π² ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ C++, ΠΏΡΠΈΡΠ΅ΠΌ Π² Π»ΡΠ±ΠΎΠΌ ΠΌΠ΅ΡΡΠ΅. ΠΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΊΠ»Π°ΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΏΠ°ΠΊΠΎΠ²ΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ Π‘ΠΠ ΠΈ HRESULT Π² ΠΎΠ΄ΠΈΠ½ ΠΊΠ»Π°ΡΡ C++:
struct COMException
{
HRESULT mhresult;
// hresult to return
// hresult Π΄Π»Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ° IErrorInfo *mpei;
// 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(constcast<OLECHAR*>(pszSource));
assert(SUCCEEDED(hr));
if (pszDesc) hr=pcei->SetDescription(constcast<OLECHAR*>(pszDesc));
assert(SUCCEEDED(hr));
if (pszHelpFile) hr=pcei->SetHelpFile(constcast<OLECHAR*>(pszHelpFile));
assert(SUCCEEDED(hr));
hr = pcei->SetHelpContext(dwHelpContext);
assert(SUCCEEDED(hr));
// hold the HRESULT and IErrorInfo ptr as data members
// ΡΠΎΡ ΡΠ°Π½ΡΠ΅ΠΌ HRESULT ΠΈ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ IErrorInfo ΠΊΠ°ΠΊ ΡΠ»Π΅ΠΌΠ΅Π½ΡΡ Π΄Π°Π½Π½ΡΡ
mhresult = hresult;
hr=pcei->QueryInterface(IIDIErrorInfo, (void**)&mpei);
assert(SUCCEEDED(hr));
pcei->Release();
}
};
Π‘ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ Π‘++-ΠΊΠ»Π°ΡΡΠ° COMException ΠΏΠΎΠΊΠ°Π·Π°Π½Π½ΡΠΉ Π²ΡΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄ Snore ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΌΠΎΠ΄ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½ ΡΠ°ΠΊ, ΡΡΠΎΠ±Ρ ΠΎΠ½ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²ΡΠ²Π°Π» Π»ΡΠ±ΡΠ΅ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ C++ Π² ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π‘ΠΠ:
STDMETHODIMP PugCat::Snore(void)
{
HRESULT hrex = SOK;
try
{
if (this->IsAsleep()) return this->DoSnore();
else throw COMException(PUGEPUGNOTASLEEP, IIDIPug, OLESTR(Β«PugCatΒ»), OLESTR(Β«I am not asleep!Β»));
}
catch (COMException& ce)
{
// a C++ COMException was thrown
// Π±ΡΠ»ΠΎ ΡΠ±ΡΠΎΡΠ΅Π½ΠΎ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ COMException C++