Get IDispatch from DLL?

E

eselk

I've got an out-of-process COM server (EXE) that I want to be able to
control from Visual Basic. I can already control it from a C/C++ app
without any issues. Under VBA in MS Access 2000, which I think is
similar to VB6, I'm able to get things to work, but now under VB 2005
(Visual Studio 2005) I can't get the same to work. Here is what I'm
doing:

1. Because the COM server only registers with the running object
table, but doesn't create class ID and prog ID registry settings (or
anything in the registry) I can use the normal GetObject function to
get the running object because VB wants to translate the class ID by
looking in the registry, and my COM server doesn't even have a class
ID. I just registers with the running object table when it is
running, using an item moniker.

2. So to get around this fact I wrote a simple DLL in C to get the
object from the running object table and return a pointer to the
object. The function is delcared as returning IDispatch* (pointer to
IDispatch).

3. Under MS Access 2000 VBA I'm able to call the DLL like this:

dim app as object
set app = GetApp()

Then I can call whatever IDispatch functions I want on "app". All
works well.

Under VB 2005, I get an error at the GetApp() line saying that a
function cannot return a variant. I don't have the exact error right
now, because I'm actually posting this for a 3rd party, but I'll try
to get it if needed.

Am I going about this the wrong way, is there an easier way, maybe one
without using a DLL? I can't change the way the COM server (EXE)
registers itself, or very much else about the server.
 
M

Mattias Sjögren

Under VB 2005, I get an error at the GetApp() line saying that a
function cannot return a variant. I don't have the exact error right
now, because I'm actually posting this for a 3rd party, but I'll try
to get it if needed.

Please post the exact error when you can, along with the signature of
the GetApp function.


Mattias
 
E

eselk

Please post the exact error when you can, along with the signature of
the GetApp function.

Mattias
From my C++ code:

extern "C" IDispatch* __export PASCAL GetApp(char *name);

The test code that works under MS Access 2000:

Private Declare Function GetApp Lib "c:\mydll.dll" (ByVal name As
String) As Object

Private Sub Command0_Click()
username = "bob"
Dim app As Object
Set app = GetApp(username)
If app Is Nothing Then
MsgBox "App not running, or not running as " & username
Exit Sub
End If
Dim msg As Object
Set msg = app.NewMessage()
Set app = Nothing
If msg Is Nothing Then
MsgBox "NewMessage failed!"
Exit Sub
End If
Dim t As Byte
t = 69
msg.Type = t
msg.To = "the to field"
msg.From = "the from field"
msg.Body = "the body" & Chr$(13) & "line 2 of the body"
msg.Subject = "the subject"
msg.Display
Set msg = Nothing
End Sub

--------
The same code which a 3rd party has said they cut and pasted into VB
for Visual Studio 2005, is giving them this error:

System.Runtime.InteropServices.MarshalDirectiveException was unhandled
Message="PInvoke restriction: cannot return variants."

at this line:

Set app = GetApp(username)

------

I guess Object is a variant in VB 2005? But in VB6 (aka VBA 2000)
Object is an IDispatch? Is there another type that I should use for
IDispatch under VB 2005? Or do I simply need to change the GetApp()
function so it passes the Object as an argument instead of a return
value? If so, what is the correct decleration on both sides to do
that?

Thanks for the time!
 
M

Mattias Sjögren

I guess Object is a variant in VB 2005?

That's the default interpretation, yes. But you can change it with an
attribute.

Private Declare Function GetApp Lib "c:\mydll.dll" (ByVal name As
String) As <MarshalAs(UnmanagedType.IDispatch)> Object


Mattias
 
E

eselk

That's the default interpretation, yes. But you can change it with an
attribute.

Private Declare Function GetApp Lib "c:\mydll.dll" (ByVal name As
String) As <MarshalAs(UnmanagedType.IDispatch)> Object

Mattias

Thank you, that worked. The 3rd party says they aren't able to get
early binding to work, but I'll let them deal with that, since they
said they are at least able to make it work with late binding. I
think they probably need to declare the object as an IDispatch now,
somehow, instead of just "Object", and then call Invoke() directly,
instead of letting "Object" call it indirectly.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top