Microsoft KB Archive/197426

= FIX: Handle Leak when Passing ADO Objects Between Processes =

Article ID: 197426

Article Last Modified on 5/17/2007

-

APPLIES TO


 * Microsoft ActiveX Data Objects 2.0

-



This article was previously published under Q197426



SYMPTOMS
When marshalling an ActiveX Data Objects (ADO) recordset between processes the handle count incrementally increases for each call made to the out-of- process component. This behavior only occurs if the rowset contains more than 8K of data.



CAUSE
This is a problem in ActiveX Data Objects Version 2.0.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This problem has been fixed in Microsoft ActiveX Data Objects versions 2.1 and later.

You can install the latest version of Microsoft Data Access Components from the following Web site:

http://msdn2.microsoft.com/en-us/data/aa937695.aspx



Steps to Reproduce the Behavior
NOTE: The following steps assume that you are using Visual Basic 5.0 or later.  Build an ActiveX .EXE that creates a disconnected recordset with ADO 2.0.  In Visual Basic, create a new ActiveX EXE project named rsEXE. Rename the default Class module to rs. Add a reference to the Microsoft ActiveX Data Objects Library.   Use the following SQL statement against the Pubs (SQL Server 6.5) database to produce a recordset that contains more than 8K of data: (SELECT authors.*, roysched.*, titleauthor.*, titles.*, publishers.* FROM titleauthor INNER JOIN authors ON titleauthor.au_id = authors.au_id INNER JOIN titles ON titleauthor.title_id = titles.title_id INNER JOIN roysched ON titles.title_id = roysched.title_id INNER JOIN publishers ON titles.pub_id = publishers.pub_id). </li> Pass the recordset as the return value of a function in the .exe.   Here is sample code for a function that returns an ADODB recordset, using the SQL above. Paste this sample code into the rs Class Module's code window: Public Function GetRs As ADODB.Recordset Dim cn As ADODB.Connection Dim Rs As ADODB.Recordset Dim strsql As String

Set cn = New ADODB.Connection cn.Open "dsn=pubs" Set Rs = New ADODB.Recordset strsql = "(SELECT authors.*, roysched.*, titleauthor.*, titles.*, " & _    "publishers.* FROM titleauthor INNER JOIN authors ON " & _     "titleauthor.au_id = authors.au_id INNER JOIN titles ON " & _      "titleauthor.title_id =  titles.title_id INNER JOIN roysched ON " & _     "titles.title_id =  roysched.title_id INNER JOIN publishers ON " & _     "titles.pub_id =  publishers.pub_id)"

Rs.CursorLocation = adUseClient Rs.LockType = adLockBatchOptimistic Rs.Open strsql, cn  Set Rs.ActiveConnection = Nothing Set GetRs = Rs

cn.Close Set cn = Nothing End Function </li> Compile the ActiveX EXE to create rsEXE.EXE.

</li></ol> </li> Create a client application that creates an instance of the .exe and calls the recordset returning function from the .exe.  In Visual Basic, create a new Standard EXE project.</li> Set a reference to the Microsoft ActiveX Data Objects Library and to the rsEXE ActiveX EXE.</li></ol> </li> It is important to maintain the scope of the .exe between calls.</li>  Repeat the call process to the .exe several times. Here is sample code that repeatedly calls a function that returns an ADO recordset from an ActiveX EXE named rsEXE, within the scope of a single procedure. Paste the sample code into the code window for the Form Load event of Form1: Dim rs1 As ADODB.Recordset Dim rs2 As ADODB.Recordset Dim rs3 As ADODB.Recordset

Set rs1 = New ADODB.Recordset Set rs2 = New ADODB.Recordset Set rs3 = New ADODB.Recordset

Dim gs As RsEXE.rs  Set gs = New RsEXE.rs  'Add rsEXE to Performance Monitor before executing the next line

Set rs1 = gs.GetRs Set rs2 = gs.GetRs Set rs3 = gs.GetRs

rs1.Close rs2.Close rs3.Close

Set rs1 = Nothing Set rs2 = Nothing Set rs3 = Nothing

Set gs = Nothing </li> Step through the client application:  After creating the ActiveX EXE object, but before calling the function that returns a recordset, open Windows NT Performance Monitor.</li> In Performance Monitor, choose Edit, Add to Chart.</li> For Object, choose Process.</li> <li>For Counter, choose Handles.</li> <li>For Instance, choose the now running ActiveX EXE.</li> <li>Return to stepping through the client application. While stepping through the client, check the handle count for the ActiveX EXE in Performance Monitor. You will see the handle count increase by 2(+/-1) for each call you make to the component.</li></ol> </li></ol>

Keywords: kbhotfixserver kbqfe kbado200fix kbado210fix kbado260fix kbbug kbdatabase kbfix kbmdac210fix kbmdacnosweep kbqfe KB197426

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.