none
Out of process C# COM server RRS feed

  • Question

  • I wrote a COM server in C#. It consists of a class and an interface that I want to expose to a C++ client. If I have the client connect to the C# COM server as an in process server, it works just fine. But if I connect to the C# COM server (same exact code) as an out of process server, the only interfaces that I can get are IUnknown and IDispatch. My custom interface does not appear to exist.

    In the C++ client, I have:


    IMyInterface * pMyInterface;
    IUnknown * pUnk;

    hr1 = CoCreateInstance( MyClassGUID, NULL, CLSCTX_INPROC_SERVER, IID_MyInterface, (void**)&pMyInterface );
    hr2 = CoCreateInstance( MyClassGUID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnk );



    In my C# code, I have:



    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), GuidAttribute( IID_MyInterface )]
    public interface MyInterface
    {
        void Run();
    }


    [Guid(MyClassGUID), ComVisible(true)]
    public class MyClass : MyInterface
    {
        public MyClass() { }

        void MyInterface.Run() { }
    }


    Both hr1 and hr2 return S_OK. But if I change CLSCTX_INPROC_SERVER to CLSCTX_LOCAL_SERVER, hr1 returns E_NOINTERFACE, and hr2 returns S_OK.

    I read somewhere that Microsoft recommends using COM+ to publish a C# COM Server as an out of proc server, and that is what I did. I have also tried a regular C# WinForm app as well.

    Can anyone tell me how to fix this so that I can deploy my C# COM server as an out of proc server and have the client find all the interfaces it publishes?

    Thanks!
    Sunday, April 12, 2009 3:37 AM

Answers

  • Out of process COM is difficult, you normally need the proxy/stub DLLs to marshal the interface across the process boundary.  The source code for those DLLs are generated by MIDL from the .idl.  Problem is, .NET doesn't use or generate .idl.  The only alternative I know is to use the standard type library marshaller.  Your interfaces must inherit from the IDispatch interface and the type library and interface IIDs must be registered properly.  And restrict themselves to using only OLE Automation compatible types, the ones that the standard marshaller knows how to marshal.

    One specifc problem in your C# code that jumps out is the [InterfaceType] attribute.  By using InterfaceIsUnknown, you specifically disable IDispatch.  Switch to IsDual.  I don't know how to take care of the registration, you may have to do this by hand.
    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Friday, April 17, 2009 10:48 AM
    Tuesday, April 14, 2009 1:31 PM
    Moderator

All replies

  • Is the typelib registered properly?
    Mattias, C# MVP
    Tuesday, April 14, 2009 12:51 PM
    Moderator
  • Out of process COM is difficult, you normally need the proxy/stub DLLs to marshal the interface across the process boundary.  The source code for those DLLs are generated by MIDL from the .idl.  Problem is, .NET doesn't use or generate .idl.  The only alternative I know is to use the standard type library marshaller.  Your interfaces must inherit from the IDispatch interface and the type library and interface IIDs must be registered properly.  And restrict themselves to using only OLE Automation compatible types, the ones that the standard marshaller knows how to marshal.

    One specifc problem in your C# code that jumps out is the [InterfaceType] attribute.  By using InterfaceIsUnknown, you specifically disable IDispatch.  Switch to IsDual.  I don't know how to take care of the registration, you may have to do this by hand.
    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Friday, April 17, 2009 10:48 AM
    Tuesday, April 14, 2009 1:31 PM
    Moderator
  • I find it strange that this is not automated if MS wanted us to use COM+ to handle out of proc C# COM servers. I don't think IDispatch is the way to go and I certainly don't want to limit the marshaling of data to OLE compatible types. Perhaps I have to rethink my approach to the problem..

    Thursday, April 16, 2009 8:32 AM
  • SurferGreggy,
    I came across this thread while doing some research on the topic...I don't know if you're still looking to make this work, I've got an example of what you're looking for (out-of-proc example using C#) and a couple of sample clients (one in C#, one in VB). I'll be glad to share those if they'd do you any good.

    cheers,
    -mjk

    Tuesday, May 5, 2009 5:40 PM
  • Hi ThinkD -

    If you wouldn't mind sharing, I'd love to see what you've got.
    You can send to me at jpek42 AT gmail.com

    Thanks for sharing!
      Jeff
    Thursday, June 11, 2009 10:30 PM
  • Hello,
       I'm encountering a similar issue whereby I'm not able to run a C# .NET App which implements/exposes a COM interface as an out of proc server from within a C++ app.
       If you could pls. pass on the sample [EMAIL REMOVED] , that would be great.

    Thx,
    Arun
    Wednesday, October 7, 2009 12:47 AM
  • Hello Jeff/ThinkD,
      If you could pls. pass on the sample/steps to run a C# .net app that exposes a COM interface within another [C++] app as an out of proc server that would be great [ arunmozhian AT hotmail.com] !
    Thanks,
    Arun
    Wednesday, October 7, 2009 6:00 PM
  • Hello

    I happen to have a complete and working sample of C# out-of-process COM server. Please check out All-In-One Code Framework and its CSExeCOMServer sample. The sample's ReadMe.txt file illustrates the detailed steps to make such a COM server. Hope it helps.

    Regards,
    Jialiang Ge
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, October 8, 2009 6:48 AM
    Moderator
  • Hello Jialiang,
      Thanks a lot for the timely help.
      The sample definitely helped me to solve my 'out of proc' piece of my COM implementation.
     From my UnManaged app , I'm now able to invoking a managed COM out of proc server.

      I've just got a few follow up questions.

      1. Instead of using an unmanaged app as a COM client, When I try to use a .net app as a COM
     client & drive the .NET COM server , although I do get the COM handle & use it , it does
     not create the process which I think probably makes sense since I just directly create the object ..
      
      code snippet used..
      //add the csexecomserver assembly reference to this project and
      ...
      ICSSimpleObject aInst= new CSSimpleObject();
      ...

     Any thoughts on how should I go about doing this will help ?
     basic intent for my .NET COM out of proc. server is to be used across various kinds of apps
      & the COM interface is the only external entity provided for interaction.

      2. Secondly my app can be invoked either via COM or just by an end user running the app since its
        a front end app.
     Any thoughts on how to differentiate these 2 scenarios [ref. count] accordingly so that the
     program does not die on the user just coz. of an external COM create/delete ?
     => Since both of them invoke the Program.Main() entry point anyways ?

       
      3. While researching this topic & after looking @ your samples, I realize that there are atleast 2 ways to go
     about implementing .net [COM] out of proc. servers [if not more!]

        1. Implementing IClassFactory in your .net app + manually add the LocalServer32 registry entry.
        2. Using ServicedComponent in your .net app & deal with all the related signing stuff.

      Just curious, whether you have any thoughts on whether one's better than the other or when is it appropriate to use one vs the other ?
     
      Finally thanks once again for the timely help with the samples.

    Thanks a lot,
    Arun

    Friday, October 9, 2009 12:59 AM
  • Hello Arun

    For the first question:
    One solution is to late bind the component. Please check out CodeFx's CSCOMClient sample. In the Program.cs file's LateBindtoComponent method, replace

    Type simpleObjType = Type.GetTypeFromProgID(
                "ATLDllCOMServer.ATLSimpleObjectSTA");

    with

    Type simpleObjType = Type.GetTypeFromProgID(
                "CSExeCOMServer.CSSimpleObject");

    For the second question:

    You need to make some modification to my CSExeCOMServer sample. CSExeCOMServer internally mimics winform message loop:

            private void RunMessageLoop()
            {
                MSG msg;
                while (NativeMethod.GetMessage(out msg, IntPtr.Zero, 0, 0))
                {
                    NativeMethod.TranslateMessage(ref msg);
                    NativeMethod.DispatchMessage(ref msg);
                }
            }

    So basically you need to make these modification:

    1. create a winform project
    2. copy & paste my PreMessageLoop to the beginning of main
    3. copy & paste my PostMessageLoop to the end of main
    4. copy & paste the COMHelper and CSSimpleObject classes to the winform project.
    5. possibly some other small modifications to make them work together in winform

    I will consider adding such a sample to CodeFx if you feel very necessary.

    For your third question,

    ServicedComponent is better than the former, because it's a Microsoft official solution, and it enables you to use COM+ features.

    Let me know if you have any other questions.


    Arun, could you please do me a favor too?
    I'm collecting feedback of the above All-In-One Code Framework project so as to persuade my managers into investing more resources to it. I hold the belief that the project can benefit many developers. Could you please send your feedback or expectation to:
    codefxf at microsoft.com?
    I appreciate it.

    Thanks
    Jialiang Ge


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, October 9, 2009 2:47 PM
    Moderator
  • Hello Jialiang,

    >> One solution is to late bind the component.
    Thanks. That was the right solution.

    >> So basically you need to make these modification:
    I already did the modifications & thats how I got my .net ui [com server] app. to work.
    Never mind about the question, I think the solution is not to exit in my situation [unless I need to start supporting remoting/DCOM].

    >> ServicedComponent is better than the former, because it's a Microsoft official solution, and it enables you to use COM+ features.
    Thanks. I'm just concerned about the whole signing part since we use a whole lot of 3rd party libraries &
    need multiple versions of our app. to coexist on the same machine. Anyways, I will try it out atleast to understand the benefits before making a decision.

    >>>Could you please send your feedback or expectation to: codefxf at microsoft.com?
    I will gladly send out the feedback.

    Thanks once again,
    Arun

    Friday, October 9, 2009 5:31 PM
  • Hello Jialiang,
      I tried to use the ServicedComponent option to create a COM out of proc server & use it with my COM CPP/.NET client, but it does not seem to work.
     I followed the CSServicedComponent sample. Signed the exe using a key pair.

      The default regsvcs seems to only create InProcserver32 entries & not LocalServer32 entries.
      This usage seems to work since it just creates the COM instance without running the app.

      Hence I manually created the entries, using reg add command line.
     While trying,
     With my Cpp  com client. I get the error 'The specified module was not found'
     With my .net com client, I get the error
        A first chance exception of type 'System.Runtime.Remoting.RemotingException' occurred in mscorlib.dll
     Cannot load type 'AssemblyName.ClasSName, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8483394fc058d254'.

      I even tried registering the exe in the gac, still its the same error.

      Although its not urgent, it would be great if you could create a sample say
     CSEXECOMServerServicedComponent or modify CSServerServicedComponent to be a COM out of proc. server.
     so that I can verify whether there's any missing pieces in my implementation.

    Thanks,
    Arun 

    Saturday, October 10, 2009 12:02 AM
  • Hello Arun

    ServicedComponent is different from oridnary COM components. ServicedComponent is hosted in COM+. It's in the form of a dll (not an exe), and is hosted in the dllhost.exe process (out-of-process). So you did not see the LocalServer32 entry.

    > CSEXECOMServerServicedComponent or modify CSServerServicedComponent to be a COM out of proc. server.
    > so that I can verify whether there's any missing pieces in my implementation.


    Serviced Component itself is already out-of-process. It cannot run by itself as an exe com server, because it's a DLL and it must be hosted in a process.

    After serviced component is register (please build my CSServicedComponent sample and run Regsvcs.exe CSServicedComponent.dll), you can call the component in the same way as you call CSExeCOMServer.

    Please let me know if you have any questions.

    BTW, thanks for your feedback of All-In-One Code Framework!

    Regards,
    Jialiang Ge
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Sunday, October 11, 2009 2:01 AM
    Moderator
  • Hello Jialiang,
     Thanks for the response. Sorry I was not aware of the COM+ architectural details.
     I guess if you need to simulate the 'exe' version effect within the ServicedComponent,
          you may have to create a new thread & run you Program.Main off that thread thus enabling the COM instance
    creation to succeed & return !
     Anyways, I'll stick with my CSEXECOMServer for my requirement.

    Thx,
    -- Arun
    Tuesday, October 13, 2009 5:18 PM
  • Hi Jialiang 

    I would really love an example of Winforms application as a out of process COM server

    Thursday, August 16, 2012 7:13 AM
  • I have serious problem with the example: The COM server is not created out-of-process.

    I need a .NET COM server which should be activated from a .NET Client. The only reason using COM between the client and the server is having out-of-process execution:

    1) my server is x86 as it uses some strictly x86 3rd party components, while the client might run inside an x64 process, where the COM object (as DLL) cannot be loaded

    2) I want to utilize an existing COM Server, i.e. using the same server instance even if activated more than one client application

    3) getting the Windows feature of out-of-process server automatic execution if and when needed (eliminating the need of a resident hosting application)

    For reasons 1) and 2) I can use a WCF based server. but it will not fulfill 3);such solution requires a resident hosting application which holds and keeps the WCF service.

    If I add a C++ based COM object, defined into a .EXE application, the COM server instance creation activates the .EXE (as the COM Server's hosting application). I expected the same behavior when the COM Server is inside a .NET based .EXE. BUT it seems this is not teh case: after adding the COM EXE server to the client application, the COM server runs inside the client application; the .EXE process is not created. This solution contradicts reasons 1), 2) and 3), so it is entirely not acceptable. for me.

    Under the CodeProject site (http://www.codeproject.com/Articles/12579/Building-COM-Servers-in-NET) there was a reference to this problem: "t may come as a surprise to some readers, but it is indeed possible to use standard COM/.NET interop techniques to instantiate a .NET class which is defined inside a .NET EXE assembly. However, there is a catch: the EXE assembly is neither executed, nor will a running instance of it be used to instantiate the required .NET class.

    Instead, the EXE assembly is loaded just like a .NET Class Library DLL into the address space of the client application, and the target class is then instantiated by the .NET Runtime".

    Is this observation correct? If not, how can I force an .EXE based COM server to be executed out-of-process, inside the (single instance) .EXE application?

    Sunday, November 11, 2012 12:10 PM