0

I am writing library plugin for application which provide COM interface IPlugin. I must implement function Start(), because that application is calling my library through ProgID and giving instance of interface there.

Short sample of usage:

[ComVisible(true)]
[Guid({GUID})]
[ClassInterface(ClassInterfaceType.None)]
public class Program : IPlugin
{
    [STAThread]
    public void Start(IInterface myInterface)
    {
        var a = myInterface.GetValue();
    }
}

When I am using interface in main thread, all went fine.

But, when I want to use that interface in other thread, I am getting exception:

Unable to cast COM object of type 'System.__ComObject' to interface type 'IInterface'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{GUID}' failed due to the follow error: No such interface supported

I tried "save" interface to GlobalInterfaceTable and "load" it on other thread, tried CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream, tried solution from this SO source and many others, always getting same error (using "saved" and "loaded" interface on same thread is still O.K., so I think, that I am using it right).

Maybe I am misunderstood something, I cannot give here all my attempts to solve it.

I am trying it so long, but I have no solution.

Please, if there is some more things to try, I'll be glad to sort it out.

jurajvt
  • 144
  • 11
  • Whomever designed this COM component needed to do extra work to ensure you could use his code on a worker thread. He didn't do it. Unless a phone call can convince him otherwise, you'll have to do the work for him, you must create a hospitable home for his code. Using [STAThread] like that is not nearly good enough, sample code [is here](https://stackoverflow.com/a/21684059/17034). – Hans Passant Dec 28 '17 at 15:46
  • @HansPassant Thank you. I tried it (I mentioned it in the question), but maybe wrong usage and misunderstanding leads to fail. Please, if it is possible, can you fit usage of that class STAThread into my case? – jurajvt Dec 28 '17 at 16:32
  • 1
    No, that attribute is only valid on the Main() entrypoint of a program. Thread.SetApartmentState() is required for a thread you create yourself. It makes a *promise*, keeping the promise requires Application.Run(). – Hans Passant Dec 28 '17 at 16:35
  • I am sorry, I don't understand. Piece of my provided code is standard single thread usage to show how it is running. Class Program is entrypoint of a program. In the implemented method Start() I am getting instance of COM component (IInterface). In that Start() method I tried to create instance of new STATThread and use BeginInvoke(). In body of invoking I tried to use myInterface which leads to same exception. As I said, I think, that I don't understand it. – jurajvt Dec 28 '17 at 16:48
  • @HansPassant Please, can you provide any example of usage of the class STAThread? I read your [suggestion](https://stackoverflow.com/a/21684059/17034) again and again, I tried to derive that class, override Initialize() and then Invoke, but still same Exception. In real scenario I am using WinForms, so normally, in Main() I have code to run MainForm. I really don't have any idea what else to do. – jurajvt Dec 28 '17 at 17:35
  • 1
    I don't know enough about this "plugin" behavior to really help you. Do favor that telephone call. Judging from your complaints and the very brief snippet, I assume that it is actually the host program that makes the Start() call. It is therefore in complete control over what thread owns the object. Without built-in proxy/stub support, you can't do anything but make calls on the thread that owns the object. Presumably the "main thread", the one that the host created. – Hans Passant Dec 28 '17 at 18:01
  • Exactly as you wrote - host program is calling Start() and provide instance of IInterface object. My collegue is making libraries for that host program like me, but in Delphi. He is using same interface (IPlugin, IInterface), but threadings goes through JvThread (from JVCL) component. And it runs well. It is some sort of wrapper I think. So I thought, that I can accomplish it in the .NET. – jurajvt Dec 28 '17 at 18:09
  • @HansPassant Please, maybe last question. As proxy/stub do you think [this](http://docwiki.embarcadero.com/RADStudio/Tokyo/en/The_Marshaling_Mechanism)? Do you think, that I can write these proxy/stubs alone, when I know GUIDs from *.tlb? – jurajvt Dec 28 '17 at 18:38

0 Answers0