1

EDIT: Question updated from information gleamed from comments below


Client: 32-bit COM client

Server: 64-bit COM in-process server configured to run out-of-process. Server makes calls to native c++ code

I am trying to run an out-of-process COM object with the help of dllhost. The 32-bit test client runs fine with each individual test case. However when I try to run the cases consecutively using a batch file, it crashes with the InteropServices.COMException: RPC failed (HRESULT 0x800706BE) . Each test case is a program with the following structure

var ComType = Type.GetTypeFromProgID("My.COMClass");
var ComObject = Activator.CreateInstance(ComType);
ComType.InvokeMember("SomeFunction", BindingFlags.InvokeMethod, null, ComObject, null);
Marshal.ReleaseComObject(ComObject);

The crash happens when I run the test in with the following fashion

//test1.bat
TestA.exe
TestB.exe //crash
//test2.bat
TestB.exe
TestA.exe //crash

There is no problem when I run each test individually. I also noticed that if I wait for the dllhost process to completely finish (and disappear) before calling the next test, the whole batch file will run without problem.

//test3.bat
TestA.exe
pause //wait a few seconds then press enter
TestB.exe //ok

Since each test run perfectly individually I assumed the code was fine and it's just a problem of how I executed the tests however I couldn't find anything about this problem so I'd appreciate any insight on this

The 64-bit COM server is actually just a COM wrapper for a C++ dll, we wrote the wrapper based on this. It's also worth mentioning that my original C++ dll was working normally before attempting the COM wrapper

AtheS21
  • 523
  • 4
  • 11
  • I see you are using late-bound COM. .NET 4 was [designed to make this much easier via `dynamic`](https://learn.microsoft.com/en-us/archive/msdn-magazine/2010/july/csharp-4-0-new-csharp-features-in-the-net-framework-4#dynamic-dispatch). try `dynamic ComObject = Activator.CreateInstance(ComType); ComType.SomeFunction();` instead –  Aug 02 '21 at 07:43
  • _"I am trying to run an out-of-process COM object `with the help of dllhost`"_ - did you want to explain why you are running the normally in-processs COM Server (containing `My.COMClass`) as out-of-process via the proxy/surrogate system? –  Aug 02 '21 at 07:50
  • _"I also noticed that if I wait for the dllhost process to completely finish (and disappear) before calling the next test, the whole batch file will run without problem"_ - are you running these tests concurrently via different threads? It's possible `My.COMClass` is not thread safe. Normally you would get an error if you used a child thread but you are also using a surrogate. Run Microsoft _OleView_, find **My.COMClass**, click it then click the **Implementation** tab and look at the **Threading Model**. If it says _Apartment_ then you should call it _one at a time_ –  Aug 02 '21 at 07:56
  • @MickyD I wanted to mention that I am using it as an out-of-process COM, but if you wonder why, it's because my client is actually 32 bit and my server is 64 bit so the surrogate is necessary (I think), I will try to use the dynamic as you suggest and see how it goes – AtheS21 Aug 02 '21 at 07:56
  • _"...my client is actually 32 bit and my server is 64 bit so the surrogate is necessary..."_ - ah yes that's perfectly fine. Don't forget to look up and see if its **Apartment** or not though (prior comment). –  Aug 02 '21 at 07:58
  • @MickyD I actually call them 1 at a time, sequentially through a batch file, it will crassh at the second test, but if I call the first test, it finished, thenI wait a few more seconds for the dllhost to go down and call the second test its fine – AtheS21 Aug 02 '21 at 07:59
  • Just confirming, 1) the 64-bit COM Server is a **.DLL**? 2) What actually is the object represented by PRODID _"My.COMClass"?_ I take it you aren't posting the real name here? 3) Is it a pure COM object or does it represent say an ActiveX control? Perhaps an OCR or barcode library? –  Aug 02 '21 at 08:06
  • @MickyD 1) yes, the COM server is a DLL. 2) It is the server dll itself and yes I just use an arbitrary name. 3) Its actually just a COM wrapper for a C++ dll, we wrote the wrapper based on [this](https://www.codeproject.com/Tips/1199539/Using-64-bit-DLLs-in-32-bit-Processes-with-Out-of) – AtheS21 Aug 02 '21 at 08:16
  • 0x800706BE is a very generic message that means the server has stopped responding to cross-process (over RPC) communication. It's likely caused by your .dll which crashes dllhost.exe for some reason. Have you checked event viewer? Or debug the .dll hosting your dll after the first call. – Simon Mourier Aug 02 '21 at 08:23
  • @SimonMourier I have checked the Event Viewer and there is no error if I just call 1 time, so I think that my dll didn't crash dllhost by itself, I wonder if it's possible for the releasing dllhost to take some time and I wasn't supposed to call again before that? – AtheS21 Aug 02 '21 at 08:47
  • @MickyD I have tried the dynamic approach but unfortunately it doesn't solve the problem, thanks for the suggestion though – AtheS21 Aug 02 '21 at 08:51
  • `dynamic` wasn't meant to be a fix –  Aug 02 '21 at 09:06
  • _"Its actually just a COM wrapper for a C++ dll"_ - thanks. Might want to expand your question alot more. It took me 5 questions to find out what you are doing. –  Aug 02 '21 at 09:09
  • @MickyD my apology, I wasn't sure what to ask and how to put the question – AtheS21 Aug 02 '21 at 09:13
  • There are 99% changes this is not a problem caused by dllhost, but by your program. Try to debug dllhost.exe where your .dll reside. – Simon Mourier Aug 02 '21 at 09:14
  • I have updated your question. Please feel free to revise as necessary :) –  Aug 02 '21 at 09:17
  • I still would like to know why your server and most likely c++ code doesn't like to be called too quickly/concurrently. Please post more code –  Aug 02 '21 at 09:18
  • @SimonMourier How do I debug dllhost.exe if I may ask? – AtheS21 Aug 02 '21 at 09:24
  • 1
    https://stackoverflow.com/questions/5541256/debugging-an-inproc-com-server-running-in-dllhost-exe – Simon Mourier Aug 02 '21 at 09:26
  • @MickyD I editted the post to explain a bit better about my situation. I dont deny the possibility of having something wrong on my C++ dll and will look into it further since apparently nobody thinks there is any hidden mechanics in using the COM that may cause this. However given the circumstance (also the C++ dll is already a shipped working product), I'm inclined to believe the C++ code was fine – AtheS21 Aug 02 '21 at 14:14
  • @SimonMourier thanks, I will look into it and see if I can debug it – AtheS21 Aug 02 '21 at 14:15

1 Answers1

0

I have found the cause of my problem. It's because my original C++ dll is creating threads to handle concurrency on its own and According to Inside COM+: Base Services, COM object code isn't supposed to do that

Since the system automatically spawns threads as necessary to enable concurrent access to the component, you should avoid calling the Win32 CreateThread function. In fact, calling CreateThread to enable concurrency in a component is strongly discouraged because in most cases this will interfere with the system's threading pooling algorithm

I'm still not entirely sure how the thread handling can lead to this problem so it would be great if someone can share a more detailed explanation but for now, it's fine as long as I remove the multi-thread code in the C++ dll.

AtheS21
  • 523
  • 4
  • 11
  • @MickyD can you please elaborate on that? I just reference the book since its statement make sense for my situation. I didn't write any code base on the book/COM+ even though it's true that I'm assuming COM and COM+ are the same – AtheS21 Aug 03 '21 at 07:33