Microsoft Knowledge Base Email Alertz

ADOEvts.exe is a sample that demonstrates how to capture events from Microsoft Active Data Objects (ADO). The ADO events in this sample were added with ADO version 2.0.

Search KbAlertz

Advanced Search

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]











Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks

Article ID: 190901 - Last Review: March 2, 2005 - Revision: 3.4

Capturing ADO Events with Visual C++

This article was previously published under Q190901

On This Page

SUMMARY

ADOEvts.exe is a sample that demonstrates how to capture events from Microsoft Active Data Objects (ADO). The ADO events in this sample were added with ADO version 2.0.

MORE INFORMATION

The following file is available for download from the Microsoft Download Center:
ADOEVTS.EXE (http://download.microsoft.com/download/vc60pro/info/1/win98/en-us/adoevts.exe)
For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591  (http://kbalertz.com/Feedback.aspx?kbNumber=119591/EN-US/ ) How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file.

To build the sample, run ADOEvts.exe, open the ADOEvts.cpp file in the Visual C++ environment, and build. When you receive a message asking if you would like to create a default project workspace click Yes. The #import of MSADO15.dll might have to be redirected if you do not have a "Program Files" directory on your C: drive.

You need to make a DataSource called "AccessTest" on the system that is pointing to the Test.mdb file provided with this sample.

After you run the console application, the events are shown in the Visual C++ Output window.

Follow these steps to capture ADO events in Visual C++:

  1. Create classes derived from RecordsetEventsVt and ConnectionEventsVt. These classes define the sink object for the events.
  2. Implement the IUnknown and RecordsetEventsVt/ConnectionEventsVt methods for each of the classes.
  3. In your application, create an instance of the event class and connect the object to the appropriate ADO connection point.
The following sample demonstrates how to implement the steps above.

Creating the Event Classes



The first step to handling ADO events is to create the sink classes that will handle the events. To do this, you must create a Visual C++ class derived from either RecordsetEventsVt or ConnectionEventsVt, depending upon the events you want to capture. The RecordsetEventsVt and ConnectionEventsVt interfaces are defined in ADOInt.h, which comes with the Microsoft Data Access SDK or Visual Studio version 6.0.

The sample shows both of the classes in ADOConnEvts.h and ADORSEvts.h. They are called CADOConnectionEvents and CADORecordsetEvents respectively. Following is the connection event class:

   ********
   #include <adoint.h>


   class CADOConnectionEvents : public ConnectionEventsVt
   {
   public :


      ULONG m_ulRefCount;
      CADOConnectionEvents():m_ulRefCount(1){}


      STDMETHOD(QueryInterface)(REFIID iid, LPVOID * ppvObject)
      {
        if (IsEqualIID(__uuidof(IUnknown), iid) ||
            IsEqualIID(__uuidof(ConnectionEventsVt), iid))
        {
          *ppvObject = this;
          return S_OK;
        }
        else
          return E_NOINTERFACE;
      }


      STDMETHOD_(ULONG, AddRef)()
      {
        return m_ulRefCount++;
      }


      STDMETHOD_(ULONG, Release)()
      {
        if (--m_ulRefCount == 0)
        {
          delete this;
          return 0;
        }
        else
          return m_ulRefCount;
      }


      STDMETHOD(InfoMessage)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(BeginTransComplete)(
               LONG TransactionLevel,
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(CommitTransComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
         *adStatus = adStatusUnwantedEvent;
         return S_OK;
      }


      STDMETHOD(RollbackTransComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(WillExecute)(
               BSTR * Source,
               CursorTypeEnum * CursorType,
               LockTypeEnum * LockType,
               long * Options,
               EventStatusEnum * adStatus,
               _ADOCommand * pCommand,
               _ADORecordset * pRecordset,
               _ADOConnection * pConnection)
      {
         *adStatus = adStatusUnwantedEvent;
         return S_OK;
      }


      STDMETHOD(ExecuteComplete)(
               LONG RecordsAffected,
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOCommand * pCommand,
               _ADORecordset * pRecordset,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(WillConnect)(
               BSTR * ConnectionString,
               BSTR * UserID,
               BSTR * Password,
               long * Options,
               EventStatusEnum * adStatus,
               _ADOConnection  *pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(ConnectComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


      STDMETHOD(Disconnect)(
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }


   };
   ********
				
Notice that you must implement Iunknown. Also, notice that all of the methods return adStatusUnwantedEvent. This tells ADO to not call the event handler again. This gives you a generic class that you can derive from and then only override the events that you want to handle. All other events are only be called once because of the adStatusUnwantedEvent return value. You can see in ADOEvents.cpp that there are 2 classes derived from these classes: CCnEvents and CRSEvents. These are the classes that you will use to create the event objects. Their methods contain an OutputDebugString message for each event so you can view the events in the output window of the debugger.

Connecting an Event Object to ADO

The ADOEvts.cpp file demonstrates how to connect an event object to an ADO connection or recordset. Four functions are defined: SetConnectionEvents(), SetRSEvents(), ClearRSEvents(), and ClearConnectionEvents(). Following is and example of how the functions are used in the main() function:
   *****
   int main(int argc, char* argv[])
   {


      CoInitialize(NULL);


      ADODB::_ConnectionPtr spConn(__uuidof(ADODB::Connection));
      ADODB::_RecordsetPtr spRS(__uuidof(ADODB::Recordset));


      SetConnectionEvents(spConn);
      spConn->Open(L"DSN=AccessTest", L"", L"", -1L);


      SetRSEvents(spRS);
      spRS->Open(L"Select * from Table1", spConn.GetInterfacePtr(),
                      ADODB::adOpenKeyset, ADODB::adLockOptimistic, -1);


      spRS->MoveFirst();
      spRS->MoveNext();


      spRS->Close();
      spConn->Close();


      ClearRSEvents(spRS);
      ClearConnectionEvents(spConn);
      return 0;


   }
   *****
				
In the code above you can see that an interface pointer to the connection and recordset objects is passed to SetConnectionEvents and SetRSEvents respectively. These functions create a connection event or recordset event object and connect it to the ADO object.

Following is the code for SetConnectionEvents():
   *****
   DWORD  gdwCnEvents;


   HRESULT SetConnectionEvents(ADODB::_ConnectionPtr & spConn)
   {


      IConnectionPointContainer   *pCPC = NULL;
      IConnectionPoint            *pCP = NULL;
      HRESULT hr;


      hr = spConn->QueryInterface(IID_IConnectionPointContainer,
                                  (LPVOID *) &pCPC);
      if (FAILED(hr))
        return hr;
      hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
      pCPC->Release();
      if (FAILED(hr))
        return hr;


      hr = pCP->Advise(new CCnEvents, &gdwCnEvents);
      pCP->Release();
      return hr;


   }
   *****
				

NOTE: UUIDs come from "ConnectionEvents" and "RecordsetEvents". The connection points QueryInterface() the event object you pass to the Advise() call for ConnectionEventsVt or RecordsetEventsVt.

Also, further notice that the pointer, "new CCnEvents", is passed directly to the Advise call. The event object is freed when its Release() method is called in the connection point Unadvise() call in ClearConnectionEvents().

APPLIES TO
  • Microsoft Data Access Components 2.7
  • Microsoft ActiveX Data Objects 2.0
  • Microsoft ActiveX Data Objects 2.1
  • Microsoft ActiveX Data Objects 2.5
  • Microsoft ActiveX Data Objects 2.6
  • Microsoft ActiveX Data Objects 2.7
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
Keywords: 
kbdownload kbdatabase kbfile kbinfo kbsample KB190901
       

Community Feedback System

Very often, it takes hours to solve a problem. Very often, you've looked high and low, and have tried a lot of solutions. When you finally found it, chances are, it was because someone else helped you. Here's your chance to give back. Use our community feedback tool to let others know what worked for you and what didn't.

Please also understand that the community feedback system is not warranted to be correct, it's simply a system that we've built to let people try and help each other. If something in a feedback response doesn't make sense to you, or you're not comfortable making changes that the feedback talks about (like registry edits), please consult a professional.

Thank you for using kbAlertz.com Feedback System.

-- Scott Cate