Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / January 2005

Tip: Looking for answers? Try searching our database.

Passing a Recordset from VB6 to VB.Net (QueryInterface failed.)

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
adam - 12 Jan 2005 16:49 GMT
I am getting an error when trying to use an ADODB.Recordset that was passed
from a VB6 application to a VB.Net class library using COM Interop. I am
running this on WinXP SP2 using the .Net Framework 1.1 and MDAC 2.8 SP1.

This is what I've done:
- I compiled the VB.Net DLL and registered it so it can be used in the VB6
app using "regasm /tlb:VBNETClass.tlb VBNETClass.dll".
- From the VB6 app, I added a reference to the VB.Net DLL.
- I added references to the ADO 2.8 Library from both the VB6 app and the
VB.Net library. (I also tried ADO 2.6 and 2.7 later but they had the same
results.)
- I built the VB6 EXE and copied it to the directory containing the VB.Net
DLL.

When I run the VB6 EXE, all of the message boxes appear fine except for the
one on the last line of PrintRecordCount below. Instead, I get the following
error:

- - - -
Run-time error '-2147467262 (80004002)';
QueryInterface for interface ADODB._Recordset failed.
- - - -
(The debugger shows it to be a System.InvalidCastException.)

Any ideas?

VB6 APP

Private Sub Command1_Click()

   Dim ccw As New VBNETClass.Class1

   Dim rs As New ADODB.Recordset
   Set rs = CreateObject("ADODB.Recordset")
   rs.CursorType = adOpenStatic
   rs.CursorLocation = adUseClient
   rs.Fields.Append "FieldName1", adVarChar, 10
   rs.Fields.Append "FieldName2", adInteger
   rs.Open

   rs.AddNew
   rs("FieldName1") = "David"
   rs("FieldName2") = 17
   rs.Update

   rs.Sort = "FieldName2"
   rs.MoveFirst

   MsgBox ("In VB6 App, about to call VB.Net class...")
' this line works
   MsgBox ("In VB6 Class, rs.RecordCount = " & rs.RecordCount)

   ccw.PrintRecordCount (rs)
   
End Sub

VB.NET CLASS LIBRARY (VBNETClass)

Public Class Class1
   Public Function PrintRecordCount(ByVal rs As ADODB.Recordset)

       MsgBox("In VB.Net Class, about to display RecordCount... ")
' this line produces the error
       MsgBox("In VB.Net Class, rs.RecordCount = " & rs.RecordCount)

   End Function
End Class

(I also tried changing the type of the input parameter to
ADODB.RecordsetClass and ADODB._Recordset but the same error resulted.)
"Peter Huang" [MSFT] - 13 Jan 2005 06:45 GMT
Hi,

I think we can use the adodb PIA  shipped with VS.NET 2003.
We can add a .NET reference to the adodb assembly which is usually located
in the path below.
<Program Files>\Microsoft.NET\Primary Interop Assemblies\adodb.dll

And then to expose the method, we can declare the VBNET class as below.
Imports ADODB
Imports System.Runtime.InteropServices

<ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class Class1
   Public Function PrintRecordCount(ByVal rs As Recordset) As Integer
       MsgBox("In VB.Net Class, about to display RecordCount... ")
       ' this line produces the error
       MsgBox("In VB.Net Class, rs.RecordCount = " & rs.RecordCount)
       Return rs.RecordCount
   End Function
   Public Function TestString() As String
       Return "Test From .NET"
   End Function
End Class

[VB6 Test code]
Private Sub Command1_Click()
   Dim ccw As New ReceiveRecordsetFromVB6_VBNET.Class1

   Dim rs As New ADODB.Recordset
   'Set rs = CreateObject("ADODB.Recordset")
   rs.CursorType = adOpenStatic
   rs.CursorLocation = adUseClient
   rs.Fields.Append "FieldName1", adVarChar, 10
   rs.Fields.Append "FieldName2", adInteger
   rs.Open

   rs.AddNew
   rs("FieldName1") = "David"
   rs("FieldName2") = 17
   rs.Update

   rs.Sort = "FieldName2"
   rs.MoveFirst

   MsgBox ("In VB6 App, about to call VB.Net class...")
' this line works
   MsgBox ("In VB6 Class, rs.RecordCount = " & rs.RecordCount)

   Debug.Print ccw.TestString()
   Debug.Print ccw.PrintRecordCount(rs)
End Sub

You may have a try and let me know the result.

Best regards,

Perter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

adam - 13 Jan 2005 19:37 GMT
Peter, thanks for the reply. I tried your code and the VB6 app successfully
executes this line:

- - - -
' this line works
  MsgBox ("In VB6 Class, rs.RecordCount = " & rs.RecordCount)
- - - -

But then I get this error:

- - - -
Run-time error '430':
Class does not support Automation or does not support expected interface
- - - -

Any ideas?

> Hi,
>
[quoted text clipped - 57 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
"Peter Huang" [MSFT] - 14 Jan 2005 01:01 GMT
Hi

Which code line report the error?
In my test code snippet below.

>     Debug.Print ccw.TestString()
>     Debug.Print ccw.PrintRecordCount(rs)

The TestString and the PrintRecordCount is two methods exposed by .NET
ClassLibrary.
Also have you  tried to add the attribute below on the class?
> <ClassInterface(ClassInterfaceType.AutoDual)> _
> Public Class Class1

Best regards,

Perter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

adam - 14 Jan 2005 14:43 GMT
This line reports the Automation error:
Debug.Print ccw.TestString()

Yes, I have added the <ClassInterface(ClassInterfaceType.AutoDual)>
attribute to Class1.

> Hi
>
[quoted text clipped - 17 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
"Peter Huang" [MSFT] - 17 Jan 2005 01:23 GMT
Hi

The TestString method is the method I added into the VB.NET Class for test
purpose, have you tried to add it  into the .NET class, also you can just
remove it?

>     Public Function TestString() As String
>         Return "Test From .NET"
>     End Function

From the error it seems that the TestString is not properly exported so the
vb6 can not call into the TestString method.
So I think you may try to copy and paste my code and rebuild and then
re-regasm the VB.NET class library to see if the problem persists.
If you still have any concern, please feel free to post here.

Best regards,

Perter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

adam - 17 Jan 2005 14:31 GMT
I have added all of the code you posted.

With the AutoDual attribute, I get the Automation error when I call either
TestString or PrintRecordCount.

If the AutoDual attribute is not used, the VB6 application is able to call
the TestString method (I get the "Test From .NET" string back.) But when I
try passing a Recordset by calling PrintRecordCount, I get the QueryInterface
error.

Does Microsoft offer any example code for passing a Recordset from VB6 to
VB.Net? It seems like a fairly common task.

> Hi
>
[quoted text clipped - 19 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.