Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

(Advanced?) Com Interop issue...

Status
Not open for further replies.

bppj

Programmer
Jun 6, 2002
24
US
I'm dealing with a legacy program which exposes a Com API through which I need to do some automation using .Net. I understand how to generate the interop classes. The issue here is that the COM IDL does NOT define a CoClass for the main application object, just an interface. (When using VB6 CreateObject, the application is instantiated by using a local server process, not in process?) Therefore, there is no ApplicationClass on which to call New. (It's not generated by tlbimp because there is no coclass) I can successfully get a reference to a running instance of the program using the Marshal.GetActiveObject() method and cast it to the Application interface.

I can also do the following to create an instance of the object:("ProgID" refers to specific progid)


Dim typ as Type = Type.GetTypeFromProgID("ProgID")
Dim app as Object = Activator.CreateInstance(typ)

Then I can use reflection all day to manipulate the api. But, if anywhere in the code I cast an object to an interface, i.e.

Dim appInterface as Application = Ctype(app, Application)

I get a com exception ("Can not create an instance of an interface") on the CreateInstance call. Mind you, this exception happens BEFORE the actual cast is made in the code. If I remove the cast, no error.

I am OBVIOUSLY missing something concerning Com interop here. Can anyone steer me in the right direction?

Thanks in advance!

B.J.
 
Does your legacy app expose a dual interface to COM?
Some C++ apps were written to only export their private interface, and you'll need to run tlbimp.exe to create the CCW for them.

If it's a VB6 app, then you should be OK (well, mostly) as VB always exported a dual interface. The problem with VB6 apps is that most VB programmers didn't set binary compatibility on their projects. So creating a CCW is worthless if the VB6 program is updated, as you get a new CLSID every time. Only solution there is to late-bind it via the Activator class.

Chip H.


If you want to get the best response to a question, please check out FAQ222-2244 first
 
Chip, thanks for the info!

I'd run tlbimp to get the interop assemblies.

As happens, the problem seems to come down to name resolution. An acquaintance pointed out that when I added the reference to the interface, it was loading the interop assembly. The progid for the application happens to be the same as the interface. So, when I tried to create the application object, it was resolving to the interop assembly's interface reference. Hence, the "Can not create an instance of an interface" error. My workaround was to create a wrapper with shared methods that creates a new appdomain(without the interop assembly loaded) creates the object and passes it back to the original domain to be cast into the interface. In pseudocode:

Code:
Public Shared Function GetApplication() As COM.Interface
   Dim otherDomainSetup As New AppDomainSetup
   otherDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
   Dim otherDomain As AppDomain = AppDomain.CreateDomain("OtherDomain", Nothing, otherDomainSetup)
   otherDomain.DoCallBack(AddressOf CreateObj)
   Return Ctype(otherDomain.GetData("app"),COM.Interface)
End Function

Public Shared Function CreateObj() as Object
  AppDomain.CurrentDomain.SetData("app", Activator.CreateInstance(Type.GetTypeFromProgID("COM.Interface")))
End Function

Hopefully this might help someone else. Any feedback/questions are welcome!

B.J.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top