INFO: Extracting Error Information from ADO in VC++ with #importLast reviewed: January 13, 1998Article ID: Q169498 |
The information in this article applies to:
SUMMARYWhen ActiveX Data Objects (ADO) encounter an error, often the Errors Collection is filled with detail on the cause of the error. This article provides sample code for extracting the maximum possible information on any errors raised by ADO within Visual C++ using #import as the mechanism to get at ADO. If ADO itself encounters an error, it does not populate the errors collection, but instead you have to use the native error mechanism to get the information--in this case an exception raised with the _com_error class. If the provider or underlying components generate error, then these will be populated in the ADO Errors Collection.
MORE INFORMATIONOften the Errors Collection returns an HRESULT in either hexadecimal format, for example, 0x80004005, or as a long value, for example, - 2147467259. These HRESULTS can be raised by underlying components such as OLE-DB or even OLE itself. When this is the case, it may be confusing since these codes are not documented in the ADO online documentation. However, frequently encountered HRESULTS can be found in the Knowledge Base article listed in the references section. The documentation for the ADO Error object indicates that the Errors Collection is populated if any error occurs within ADO or its underlying provider. This is somewhat incorrect. Depending on the source of the error, or even bugs in the underyling provider to ADO (OLE-DB) or within ADO itself, the errors collection may not be populated. You need to track the HRESULT returned by many ADO methods, as well as if the _com_error exception has been raised by #import generated classes. The Errors Collection is available only off the Connection object, so you need to initialize ADO off of a Connection object. Below is sample code that demonstrates how to open a connection and report any errors encountered, as well as handling Exceptions, and cracking the returned HRESULT:
// Obtain the error message for a given HRESULT CString LogCrackHR( HRESULT hr ) { LPVOID lpMsgBuf; CString strTmp; ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // STR_TMP is defined within LOG.CPP to provide safe format string // for both ANSI and UNICODE strTmp.Format( STR_TMP, (char *) lpMsgBuf ); // Free the buffer. ::LocalFree( lpMsgBuf ); return strTmp; } // Obtain information from the Errors Collection HRESULT LogAdoErrorImport(_ConnectionPtr pConn) { ErrorsPtr pErrors; ErrorPtr pError; CString strTmp; HRESULT hr = (HRESULT) 0L; long nCount; // Don't have an un-handled exception in the handler that // handles exceptions! try { pErrors = pConn->GetErrors(); nCount = pErrors->GetCount(); for( long i = 0; (!FAILED(hr)) && (i < nCount); i++ ) { TRACE( "\t Dumping ADO Error %d of %d", i+1, nCount ); hr = pErrors->get_Item((_variant_t)((long)i), &pError ); _bstr_t bstrSource ( pError->GetSource() ); _bstr_t bstrDescription( pError->GetDescription() ); _bstr_t bstrHelpFile ( pError->GetHelpFile() ); _bstr_t bstrSQLState ( pError->GetSQLState() ); TRACE( "\t\t Number = %ld", pError->GetNumber() ); TRACE( "\t\t Source = %s", (LPCTSTR) bstrSource ); TRACE( "\t\t Description = %s", (LPCTSTR) bstrDescription ); TRACE( "\t\t HelpFile = %s", (LPCTSTR) bstrHelpFile ); TRACE( "\t\t HelpContext = %ld", pError->GetHelpContext() ); TRACE( "\t\t SQLState = %s", (LPCTSTR) bstrSQLState ); TRACE( "\t\t HelpContext = %ld", pError->GetHelpContext() ); TRACE( "\t\t NativeError = %ld", pError->GetNativeError() ); } } catch( CException *e ) { TRACE( "*** UNABLE TO LOG EXCEPTION ***" ); e->Delete(); } catch(...) { TRACE( "*** UNABLE TO LOG EXCEPTION ***" ); } pErrors->Release(); pError->Release(); return hr; } void CAdoDemoDlg::OnAdoTest() { HRESULT hr = S_OK; _ConnectionPtr pConn; hr = ::CoInitialize( NULL ); if( !FAILED( hr ) ) hr = pConn.CreateInstance( __uuidof( Connection ) ); // The exception handling below assumes a valid Connection object, // so drop out if we couldn't create one for any reason. if ( FAILED(hr) ) return; try { // ... Your code goes here pConn->Close(); // For any error condition, dump results to TRACE // You may get a failure that does not raise an exception // The ADO Errors collection will likely be empty, but // check anyway if( FAILED( hr ) ) { TRACE( "*** HRESULT ***" ); TRACE( LogCrackHR( hr ) ); LogAdoErrorImport(_ConnectionPtr pConn) } } catch( CException *e ) { TRACE( "*** Unhandled MFC Exception ***" ); e->Delete(); } catch( _com_error &e ) { // Crack _com_error _bstr_t bstrSource(e.Source()); _bstr_t bstrDescription(e.Description()); TRACE( "Exception thrown for classes generated by #import" ); TRACE( "\tCode = %08lx\n", e.Error()); TRACE( "\tCode meaning = %s\n", e.ErrorMessage()); TRACE( "\tSource = %s\n", (LPCTSTR) bstrSource); TRACE( "\tDescription = %s\n", (LPCTSTR) bstrDescription); // Errors Collection may not always be populated if( FAILED( hr ) ) { TRACE( "*** HRESULT ***" ); TRACE( LogCrackHR( hr ) ); } // Crack Errors Collection LogAdoErrorImport(pConn); } catch(...) { TRACE( "*** Unhandled Exception ***" ); } } REFERENCESFor additional information, please see the following articles in the Microsoft Knowledge Base:
ARTICLE-ID: Q168354 TITLE : INFO: Underlying OLE and OLEDB Provider Errors Exposed via ADO ARTICLE-ID: q167802 TITLE : SAMPLE: EXCEPTEX Traps MFC and Win32 Structured Exceptions Keywords : kbcode adoengdb adovc Platform : WINDOWS Issue type : kbinfo |
================================================================================
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |