-
Com Interop and VB6 Collections
One of the goals of COM interopability is (to paraphrase slightly) 'that
either the client or the server portion of existing applications can be
upgraded to .NET independently without impacting the functionality of the
application.'
Bearing this in mind I created a simple VB6 client and server and after
learning a bit about COM interop attributes was able to replace the
VB6 server with a VB7 server. After running RegAsm.exe the VB6 client used
the
the VB7 server without any change whatever - certainly no need for a
recompilation. Top marks for .NET developers!
I had a lot more trouble with my second example where the VB6 server I was
replacing used a VB6 collection; surely a very likely case in practice.
Here is the code of my example server followed by the Form.Load method
of the trivial client which will show 'Greetings from V6' in the
labresult label of its only form. This in turn is followed by the IDL
of V6Server.dll' s type library as displayed by oleview.exe
-----------------------------------V6Server Create.cls
Option Explicit
Public Function Results() As Collection
Dim col As New Collection
col.Add "Greetings from V6"
Set Results = col
End Function
------------------------------------V6Client FClient.frm
Private Sub Form_Load()
Dim svr As New V6Server.Create
Dim col As Collection
Set col = svr.Results
labResults = col(1)
End Sub
-------------------------------------IDL from V6Server.dll
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: V6Server.dll
[
uuid(AF929B74-60DA-4040-997C-4A953DDA5D68),
version(1.0)
]
library V6Server
{
// TLib : // TLib : OLE Automation :
{00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// TLib : Visual Basic For Applications :
{000204EF-0000-0000-C000-000000000046}
importlib("MSVBVM60.DLL");
// Forward declare all types defined in this typelib
interface _Create;
[
odl,
uuid(5625567F-5568-4DC5-A010-6D22496B0E5F),
version(1.0),
hidden,
dual,
nonextensible,
oleautomation
]
interface _Create : IDispatch {
[id(0x60030000)]
HRESULT Results([out, retval] _Collection** );
};
[
uuid(DD5C041B-73E8-467D-9E4D-F378E37B65F1),
version(1.0)
]
coclass Create {
[default] interface _Create;
};
};
--------------------------------------------------------------------------
When I had got this far I realised that the V7 server project would need
to make a COM reference to MSVBVM60.DLL ie VBA version 6. Here is the
code that eventually succesfully replaced VB6Server.dll and, after RegAsm
caused VB6Client to show the message 'Greetings from VB7' in its label.
(Note how MSVBVM60.DLL has been imported as assembly VBA)
-----------------------------------------------V7Server.dll
<Assembly: System.Runtime.InteropServices.GUID _
("AF929B74-60DA-4040-997C-4A953DDA5D68")>
Imports System.Runtime.InteropServices
Interface <GUID("5625567F-5568-4DC5-A010-6D22496B0E5F")> _Create
Function Results() As VBA._Collection
End Interface
Public Class <HasDefaultInterface(), _
GUID("DD5C041B-73E8-467D-9E4D-F378E37B65F1")> Create
Implements _Create
Public Function Results() As VBA._Collection Implements _Create.Results
Dim srv As New V7Helper.CMake() 'THIS IS LAME
Dim col As VBA._Collection = srv.NewCol 'AND SO IS THIS
col.Add("Greetings from V7")
Return col
End Function
End Class
------------------------------------------------------------------------
Now, really the two lines commented 'THIS IS LAME AND SO IS THIS' are
subject of this note. There didn't seem to be anything strange about
VBA.Collection as far as the browser was concerned and the compiler
happily compiled
Dim coln As New VBA.Collection()
Dim col As VBA._Collection = CType(coln, VBA._Collection)
which I would have liked to use in their place. However, when run, the
first line suffers:
System.Runtime.InteropServices.COMException: Class not registered
but if you look for the CLSID in the registry it seems to be there OK:
[HKEY_CLASSES_ROOT\CLSID\{A4C4671C-499F-101B-BB78-00AA00383CBB}\InprocServer
32]
"Class"="VBA.Collection"
"Assembly"="VBA, Ver=6.0.0.0, Loc=\"\", SN=null"
I've tried hacking the registry a bit to no avail so I gave up and wrote
VSHelper.dll in VB6 then made it a COM reference.
---------------------------------------V7Helper.dll CMake.cls----------
Public Function NewCol() As Collection
Dim col As New Collection
Set NewCol = col
End Function
------------------------------------------------------------------------
So the question I raise is 'Is there a better way of doing this?' or is
there one planned for when VB7 ships?
-
Re: Com Interop and VB6 Collections
>I had a lot more trouble with my second example where the VB6 server I was
>replacing used a VB6 collection; surely a very likely case in practice.
If this is a common practice, then it's an unforunate one because Collection
is a private class (just like App, Printer, Clipboard, Form, etc.) that you
are not allowed to export/expose from public members of your ActiveX objects.
The fact that VB does not explicitly warn against this is probably the cause
of this practice, but the docs definitely warn against it.
-
Re: Com Interop and VB6 Collections
"Atif Aziz" <atifa@microsoft.com> wrote in message
news:3a730944$1@news.devx.com...
>
> >I had a lot more trouble with my second example where the VB6 server I
was
> >replacing used a VB6 collection; surely a very likely case in practice.
>
> If this is a common practice, then it's an unforunate one because
Collection
> is a private class (just like App, Printer, Clipboard, Form, etc.) that
you
> are not allowed to export/expose from public members of your ActiveX
objects.
> The fact that VB does not explicitly warn against this is probably the
cause
> of this practice, but the docs definitely warn against it.
Thanks for replying to my post. Here is an extract from the VB6
documentation on
The Jan 2001 MSDN Library
__________________________________________________________________
Visual Basic Concepts
Data Types Allowed in Properties and Methods
Classes can have properties and methods of any public data type supported by
Automation. This includes all arguments of properties and methods, as well
their return values. The allowed data types include:
Public objects provided by another component, such as DAO or a component
authored using Visual Basic.
Public objects provided by Visual Basic for applications, such as the Error
and Collection objects
<some other allowable stuff snipped>
__________________________________________________________________
So this is a real problem. The private classes you refer to DO NOT include
collections, but do included forms, and controls as indicated a little later
in this
documentation
__________________________________________________________________
On the Evils of Returning Private Objects
The following data types are not allowed, and references to them should
never be returned to client applications:
All of the objects provided in the Visual Basic (VB) object library - for
example, controls. Use the Object Browser to view the entire list.
All forms.
All class modules whose Instancing property is set to Private.
________________________________________________________________
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Development Centers
-- Android Development Center
-- Cloud Development Project Center
-- HTML5 Development Center
-- Windows Mobile Development Center
|