3

It's hard to explain our situaction.

We have a 3-tier application. The engine is a DLL coded in C++, then we have a VB6 ActiveX EXE that access to the engine via API calls, and at the top level we have a Excel Addin (in C# using VSTO framework) calling the middle layer with an interop DLL. At this time, each "connection" from the Addin to the engine creates a new EXE (VB6 uses API calls to access to the engine) and all works fine. Now we are moving the middle layer to .NET, it works 'presumably' fine (it pass all our Unit test) but, we found an error when we open 2 "connections" at same time (ups, no unit test check this situation because it's a new behavour). The DLL have static objects that it's shared over all instances in the same process and we have interactions between "connections". In our old version each "connection" creates a new EXE with no memory sharing between processes, now it's the same process and they share memory and the static objects.

Following the tips from this question. We tried to build a COM EXE in C# to do an out-of-process objects in the middle layer but we have the same result. They share the static objects, at the end, each connection not creates a independent process.

It's clear, but not affordable at this time, moving API calls to ATL or changing the static objects to instanciable references with a handle and change all the API calls to get/set this handlers. I reviewed all examples in MS All-in-one but I didn't find any solution. Neither it's possible to keep only one connection at time, each workbook can have one connection and in the future we want to explore a Web application with multiple connections at same time.

Any suggestion?

Thanks in advance,

Community
  • 1
  • 1
Oriol Terradas
  • 1,728
  • 2
  • 18
  • 30

3 Answers3

3

Whether COM starts new EXE per each COM object, or uses single EXE to instantiate all the object is controlled by flags parameters passed to CoRegisterClassObject. See

http://msdn.microsoft.com/en-us/library/ms693407(v=vs.85).aspx, and

http://msdn.microsoft.com/en-us/library/ms679697(v=vs.85).aspx

You need to pass REGCLS_SINGLEUSE or REGCLS_MULTI_SEPARATE flags.

Now, the trick is to pass this flag, as you might not call this method directly - the details depend on how you implemented the COM EXE.

Michael Entin
  • 4,936
  • 2
  • 19
  • 21
  • Great! I found a solution following your suggestions. Using the example "VBExeCOMServer" from All-in-one code (http://1code.codeplex.com/) changing the call to CoRegisterClassObject from MULTIPLEUSE to SINGLEUSE, and each time a new EXE instance is created an it works fine and it avoids the singleton sharing objects. Thx for all suggestions. – Oriol Terradas Jun 08 '11 at 13:34
2

it's not clear from the question, but it sounds like the "middle layer" you have was built as a VB6 EXE, and you're trying to replace it with a .net DLL. If that's the case, you'll definitely get the behavior you describe.

With a VB6 EXE com project, instantiating a new object starts a new process. With a .net dll (or a Vb6 dll really) you +won't+ get a new process.

You'd either need to create a .net EXE that exposes COM objects just like your VB6 exe does, or (sounds like you've already investigated this) you'll need to refactor your EXE objects to properly handle multiple instances within a single process.

Honestly, it'd probably be better to do that latter, since relying on singletons like this is generally a bad code smell. But it a pinch, you should be able to replicate the behavior of the VB6 exe with a .net project. You just can't do it in a dll.

DarinH
  • 4,768
  • 2
  • 20
  • 32
  • I tried to build an EXE with a .net project but it seems that it doesn't work. When I create new instance of a object from the middle layer, no new EXE is created like VB6-ActiveX-EXE (taskmanager doesn't show new process), it seems like it's created inside the CLR, different threat but not different process. Could it be? – Oriol Terradas May 27 '11 at 07:52
1

Was your middle layer created in .Net? If it was, you might be facing the issue that your COM class is been created as a native .net object instead of a COM object. The solution usually involve using Primary Interop Assemblies. Take a look on this SO question to see if it matches your problem.

Community
  • 1
  • 1
yms
  • 10,080
  • 3
  • 37
  • 66