Hello,
We are having a problem with com interop. We have a Visual Foxpro dll (
FOXPRO 8 ) that returns an ADODB.Recordset
The fox dll is compiled as an Com+ dll. When we use that dll in ASP it works
fine. When we try to use it in a c# application ( Windows or ASP.NET ) we
keep getting exceptions.
The first idea was to try the same thing with a VB com+ dll, but the same
error occurs. It seems that the wrapper class generated by Visual studio .net
doesn't function correctly.
Below i will describe a few tests we did to find the source of the problem.
We have a Com dll with the following Fox Code
DEFINE CLASS testADODB as Session Olepublic
PROCEDURE moGetRecordSet as ADODB.RecordSet
loDB = CREATEOBJECT("test.testADODB_DB")
RETURN loDB.moGetRecordSet
ENDPROC
ENDDEFINE
DEFINE CLASS testADODB_DB as Session Olepublic
PROCEDURE moGetRecordSet
loRS = CREATEOBJECT("ADODB.RecordSet")
RETURN loRS
ENDPROC
ENDDEFINE
When i create a wrapper class in VS.NET 2003 ( By adding a reference to a
COM dll ) and call the Com DLL with the following c# code
test.testADODBClass testClass = new test.testADODBClass();
ADODB.Recordset recset = testClass.moGetRecordSet();
if( recset == null )
return;
if( recset.State > 0 )
{
lblResult.Text = "RecCount: " + recset.RecordCount;
}
else
{
lblResult.Text = recset.GetType().ToString();
}
This code compiles just fine, but when I run this code i get an
ExecutionEngineException. When I look in the documentation of this exception
the remarks say: "Execution engine errors are fatal errors that should never
occur." so that doesn't help either.
The strange thing is that if I change the FOX dll defenition so that the
return type is a variant instead of a ADODB.Recordset and cast it to an
ADODB.Recordset in my C# code it works correctly.
I'm also pretty sure the Com dll is correct because it works fine in classic
asp and it is also possible to call the dll itself with the following C# code.
object comObj;
Type comType;
comType = Type.GetTypeFromProgID( "myComProgID" );
comObj = Activator.CreateInstance( comType );
object ret = comType.InvokeMember( "myComFunction"
, BindingFlags.InvokeMethod | BindingFlags.Default
, null
, comObj
, new object[]{ "param1","param2", "param3" } );
ADODB.Recordset recset = (ADODB.Recordset)ret;
MessageBox.Show( recset.RecordCount.ToString() );
So I think there is something wrong with the interop assembly generated by
VS.NET. How can i use the COM wrappers generated by VS.net without getting
this exception?
Gary Chang[MSFT] - 16 Oct 2004 08:32 GMT
Hi Agis,
Currently I am looking for somebody who could help you on it. We will reply
here with more information as soon as possible.
If you have any more concerns on it, please feel free to post here.
Thanks for your understanding!
Best regards,
Gary Chang
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
"Peter Huang" - 18 Oct 2004 10:44 GMT
Hi
I think you may try to call the VB6 as below.
Also which code line cause the ExecutionEngineException? When we create the
object or when we invoke the method on the object?
Is there any problem when the dll is not in the COM+?
Please make the test based on my code so that we can make sure that we are
working on one problem.
[VB6Dll]
Dim rs As Recordset
Dim cn As Connection
Public Function rtRecordSet() As Recordset
rs.Open "select * from customers", cn, adOpenDynamic
Set rtRecordSet = rs
End Function
Private Sub Class_Initialize()
Set cn = New Connection
Set rs = New Recordset
cn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=Northwind;Data Source=machine"
cn.CursorLocation = adUseClient
cn.Open
End Sub
Private Sub Class_Terminate()
rs.Close
cn.Close
End Sub
[.net test code]
Add a reference to the vb6 dll.
private void button1_Click(object sender, System.EventArgs e)
{
ReproRecordSetLib.ReproRecordSetClsClass o= new
ReproRecordSetLib.ReproRecordSetClsClass();
ADODB.Recordset rs = o.rtRecordSet();
MessageBox.Show(rs.RecordCount.ToString());
}
Best regards,
Peter 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.
Agis - 20 Oct 2004 09:45 GMT
We tried the code you posted. We discovered that it works fine if we don’t
run the component under the component manager. If we run the component under
the component manager ( of windows 2000 SP 3 ) we get a Exception.
This is not the ExecutionEngineException we got earlier but an COMException
with the message “QueryInterface for interface Project1._class1 failed”.
The stacktrace of the exception:
· -----[Core exception]--------------------
at WindowsApplication1.Form1.MSTest() in c:\documents and
settings\r.versteeg\my documents\visual studio
projects\windowsapplication1\form1.cs:line 227
In MSTest() we used this code
try
{
Project1.Class1Class o = new Project1.Class1Class();
ADODB.Recordset rs = o.rtRecordSet();
MessageBox.Show( rs.RecordCount.ToString() );
}
catch( Exception ex )
{
ExceptionViewer viewer = new ExceptionViewer( ex );
viewer.ShowDialog();
}
The ExceptionViewer class is just a simple window to show the properties of
the exception.
The exception is thrown at the line where we call the rtRecordSet() method.
When we run the code if the component doesn’t run under the component
manager we get a messagebox with the number 91 just as excpected because 91
rows are returned by the query.
We use v1.1.4322 of the .NET Framework and VS.NET 2003.
We used this VB6 Code as you sugested:
Dim rs As Recordset
Dim cn As Connection
Public Function rtRecordSet() As Recordset
rs.Open "select * from customers", cn, adOpenDynamic
Set rtRecordSet = rs
End Function
Private Sub Class_Initialize()
Set cn = New Connection
Set rs = New Recordset
cn.ConnectionString = "Provider=SQLOLEDB.1;user
id=username;password=password;Persist Security Info=False;Initial
Catalog=Northwind;Data Source=CommerceSvr"
cn.CursorLocation = adUseClient
cn.Open
End Sub
Private Sub Class_Terminate()
rs.Close
cn.Close
End Sub
"Peter Huang" - 21 Oct 2004 06:25 GMT
Hi
To isolate the problem, I think you may try to make a VB6 client to access
to the com object (hosted in com+)with the similar code to see if there is
any problem.
You may perform the test and let me know the result.
Best regards,
Peter 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.