4

We have a COM interface declared and implemented in unmanaged C++. We no longer wish to maintain this assembly, but do need to make some changes, and still be backward compatible.

What I want to do, is to write all the new code in C#, and make it ComVisible. From this thread I see a reference to TreatAs to replace the old interface.

I was thinking along the same path as Jonathan Peppers regarding ProgId, Guid, etc. I will implement the exact interface as the old version as a wrapper to the new implementation. I am also thinking about adding MarshalAs attributes exactly as in the generated interop wrapper to be sure the data types will be the same, if possible.

Are there anything else I should consider while working with this? Anyone with experience doing this conversion?

EDIT: I do have the IDL file for the server. I am not sure if there is a way I can auto generate the code based on this. COM is not something I'm very familiar with.

EDIT Q: How should I deal with HRESULT used by existing clients?

ADDED: Figured I should point other readers to a different fix, which is not available for my scenario as I can't recompile all the .NET applications using the existing com:

Bjørnar Sundsbø

3
  • It is simple when you have an .idl file or the type library of the original server. It won't be if you don't or when the COM interface(s) are not automation compatible. Update your question with this essential info. Commented Aug 16, 2011 at 14:06
  • Is there a way I can generate server side code from the type library or idl instead of a client wrapper? Commented Aug 16, 2011 at 15:20
  • A type library only contains declarations, no code. You'll have to rewrite the code, that was your intention afaict. Commented Aug 16, 2011 at 15:27

2 Answers 2

2

One quick way to get started:

  • Import your existing COM object into C# with tlbimp (or Visual Studio)
  • Load up .Net Reflector and get the generated interface to put in your new project
  • Implement the generated interface in C#
  • Switch any import declarations to export instead

This should get all your types and method signatures correct from the start. It is a great starting point for porting an existing COM interface to C#.

Sign up to request clarification or add additional context in comments.

11 Comments

Or use dotPeek instead of Reflector since the latter now costs money.
Do you mean replace ComImport with ComVisible? I have now used .NET Reflector and the FileDisassembler to generate my code. This code does include things like MethodIml(MethodImplOptions and method code type. Should I keep these?
Yes, change ComImport to ComVisible. In the past, I believe I removed MethodImpl with no issue.
I've had some luck. Extracted the interface specs from the original type library, edited some attributes, and registered the assembly for COM. The trouble now is that when constructing the object on the client, I get the following exception: Unable to cast object of type 'Interop.TC30Lib.TC30ClientClass' to type 'Interop.TC30Lib.TC30ClientClass'. I have kept the original COM wrapper used by the application, which is what I need to do to support existing applications. Any suggestions?
Sorry. The last exception was introduced when I tried adding the COM object to GAC because of the following exception: System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {A47E5E67-E8FF-4DD6-B4D7-FDC83B931146} failed due to the following error: 80070002 The system cannot find the file specified. (Exception from HRESULT: 0x80070002).
|
1

It seems to be by design to prevent managed COM object from being used from a managed client.

Here are some links to the same problem, as well as this thread, providing some solutions. Also take a look at the answer Jonathan Peppers provided to see how to start out if you only need to use it from unmanaged applications.

The only way I figure I could work around this, is a messy solution where I create the new code in C#, add a COM layer on top of that. Then create an additional COM layer as unmanaged C++ which accesses the first layer so, that my .NET applications can access it. {Unmanaged COM exposing the original interface} => {Managed COM with rewrite of the original logic of the COM}. All existing applications will then access the "{Unmanaged COM...}". If I get desperate enough, that might be a way. For now I'm abandoning this approach and looking for other solutions.

If you can, recompile your managed application to use the new assembly, do so. You can still use that managed COM from VB6, unmanaged C++, etc. If you still need to reference as a COM from managed, you might be able to create new instances using the approach specified in one of the referenced posts, as long as you don't need to create an interop wrapper.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.