none
Using WCF Service Reference within a COM Object RRS feed

  • Question

  • Hello all,

    My task sounds simple, but running into some hard-to-debug issues.  Here is my task: Create a C# library with a service reference (to a WCF service) and make this library available to native C++ code by using a COM wrapper.  I got this to work fine without the service reference (followed https://support.microsoft.com/en-us/kb/828736)

    - Create C# library with public interface

    - under properties > Application >  checked "Make assembly COM-Visible"

    - under properties > Build checked "Register for COM interop"

    I can call that from my native C++ code fine.  Once I make an instance of the service reference in the C# library class constructor it fails.  Everything builds and links w/o errors or warnings.  In C++ when I try to create my interface pointer I get this generic error: "Microsoft C++ exception: _com_error at memory location...".  Diving into the C++ MS code, it crashes in "_com_prt_t::CreateInstance" when calling "CoCreateInstance".  The HRESULT is "REGDB_E_CLASSNOTREF Class not registered".

    If I do not instantiate the service object in the C# library constructor the COM object is created successfully, however any class that does the instantiation (of the service reference) will fail.

    I have changed the C# library to build for x86 with no change.  To remove initial warnings I changed my service reference to internal so that they are not publically accessible in the interface.

    I am using MSVC 2013 and .NET 4.5.

    Any thoughts or advice is very helpful.  Is this possible??

    Thursday, May 28, 2015 12:27 AM

Answers

  • Found my answer!  I am new to COM objects and really this problem really had nothing to do with it.  Let me explain how I found my answer to help anyone else struggling to begin...

    First, the error messages outlined above are very generic.  This is because my C# code threw an uncaught exception and it boiled up to the C++ side as a generic memory problem.  The issue was that my C# service client, running in the COM module, could not locate app.config.  I setup configuration programmatically generating a BasicHttpBinding() and EndpointAddress() and it worked great.  Still need to figure out where to put app.config... 

    The way I figured this out was round-about, but here is what I did.  I first tried in a separate thread (crazy I know).  This, however, printed out the correct exception since that thread wasn't linked back to the COM (not sure I understand that completely but it worked).  Then, once I understood what was happening, a simple try-catch allowed me to handle the exception elegantly and continue on.

    Hope this is helpful for other COM newbies.  Really cool technology once you get your bearings. 

    • Marked as answer by rjsctd Thursday, May 28, 2015 9:19 PM
    Thursday, May 28, 2015 9:19 PM

All replies

  • hi BigRStrongRProgrammR,
         According to this case, I am suspecting that you might be used parameter constructor in the corresponding c# Library. Basically When you create an instance for the particular class, then its corresponding constructor invoked automatically. According to the WCF, it doesn't support parameterized constructor.
    So you could avoid parameterized constructors because only the default constructor will ever be used by WCF. Even though the class can use internal properties, indexers, and static members respectively.
    Thursday, May 28, 2015 7:10 AM
  • Thank you for your reply Edwin, but this is not the case.  I am using the default constructor, the only issue is creating the service client within the COM object.  I can create the client and exercise the service correctly through unit tests.  Here is some code example to help me explain:

    C#

    public class CSClass : ICSClass
    {
     private ServiceReferenceNamespace.ServiceReferenceClient client;
     public CSClass()
     {
      client = new ServiceReferenceNamespace.ServiceReferenceClient();
     }

     public bool RetTrue()
     {
      return true;
     }
     ...
     

    C++

    #import "..\bin\Debug\CSClass.tlb" raw_interfaces_only
    int _tmain(int argc, _TCHAR* argv[])
    {
     // Initialize COM.
     HRESULT hr = CoInitialize(NULL);

     // Create the interface pointer.
     CSClassNameSpace::ICSClassPtr pICSClass(__uuidof(CSClassNameSpace::CSClass));
     VARIANT_BOOL ret = false;
     pICSClass->RetTrue(&ret);
     ...

    The C# class communicates with the service reference fine when not being used in a COM assembly.  The line "client = new ServiceReferenceNamespace.ServiceReferenceClient();" will cause the creation of pICSClass to fail.  Commenting this line out will cause everything to work as intended, and RetTrue(&ret) will set the ret VARIANT_BOOL to true correctly.  However, if I move the client instantiation in C# ("client = new ServiceReferenceNamespace.ServiceReferenceClient();") into the RetTrue() method above, then the pICSClass will be created correctly and when calling the RetTrue(&ret) function it will fail (the ret VARIANT_BOOL will remain false).

    Thursday, May 28, 2015 2:14 PM
  • Found my answer!  I am new to COM objects and really this problem really had nothing to do with it.  Let me explain how I found my answer to help anyone else struggling to begin...

    First, the error messages outlined above are very generic.  This is because my C# code threw an uncaught exception and it boiled up to the C++ side as a generic memory problem.  The issue was that my C# service client, running in the COM module, could not locate app.config.  I setup configuration programmatically generating a BasicHttpBinding() and EndpointAddress() and it worked great.  Still need to figure out where to put app.config... 

    The way I figured this out was round-about, but here is what I did.  I first tried in a separate thread (crazy I know).  This, however, printed out the correct exception since that thread wasn't linked back to the COM (not sure I understand that completely but it worked).  Then, once I understood what was happening, a simple try-catch allowed me to handle the exception elegantly and continue on.

    Hope this is helpful for other COM newbies.  Really cool technology once you get your bearings. 

    • Marked as answer by rjsctd Thursday, May 28, 2015 9:19 PM
    Thursday, May 28, 2015 9:19 PM