Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 970235
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T02:46:23+00:00 2026-05-16T02:46:23+00:00

hi have a COM visible API in C# which looks like the following: public

  • 0

hi have a COM visible API in C# which looks like the following:

public void DoSomething(string par1, string par2, object additionalParameter)

The idea is that based on the value of the string parameters I expect a different class as the third parameter and cast it appropriately in the implementation (I know this design is not optimal but I don’t have much flexibility here).

Suppose that for some combination of the string parameters the type of the additional parameter is the following:

[ComVisible(true)]
[Serializable]
public class TestObject    
{
    public string String{ get; set; }

    public long Long { get; set; }
}

I need to my API method from some unmanaged code; however I am having difficulties in creating the a proper variant needed for the third parameter.

I am using the CComVariant(...) passing an IDispatch pointing to a TestObject that I have just built.

Suppose that pTestObject is an IDispatch pointer to my TestObject, I have something like the following:

CComVariant pObjectVariant(pTestObject);
DoSomething(BSTR(L"first"), BSTR(L"second"), pObjectVariant);

However, when the C# function is finally invoked, I see that the object has type bool instead of TestObject that I was expecting.

Any idea?

Stefano

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T02:46:24+00:00Added an answer on May 16, 2026 at 2:46 am

    I have a couple of suggestions. First of all, create an interface for anything that you touch in COM, even if its just a bog-standard DTO that has no methods and only properties. COM loves interfaces. It loves them so much, that everything you touch in COM is an interface.

    The other suggestion is that you place a GuidAttribute on anything that you touch in COM. This will ensure that your registry doesn’t get crapped up when you register the managed assembly with COM. COM loves GUIDs more than it loves interfaces, and it gets confused easily if an interface is registered to more than one GUID, which can happen if you don’t hard-fix the interface GUIDs in code. Concrete classes also need a GUIDAttribute.

    I know it sucks, but that’s why MS is trying so hard to get people away from using COM.

    That being said, you probably want C# like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ClassLibrary1
    {
    
        [ComVisible(true)]
        [Guid("1CEB24F2-BF13-417F-B5BC-DB8E82A56EAE")]
        public interface ITestEntity1 //This is how TestEntity1 is visible to the COM code...so it needs a Guid.
        {
            bool Thing { get; set; }
        }
    
    
        [ComVisible(true)]
        [Guid("C8B5A7C2-F67C-4271-A762-3642754F2233")]
        public class TestEntity1 : ITestEntity1  //Created by the COM runtime...needs a Guid.
        {
            public bool Thing { get; set; }
        }
    
        [ComVisible(true)]
        [Guid("8904A7EC-D865-4533-91EC-1F68524651D0")]
        public interface ITestEntity2
        {
            string Description { get; set; }
        }
    
        [ComVisible(true)]
        [Guid("668EE2E8-5A60-468B-8689-D9327090AA44")]
        public class TestEntity2 : ITestEntity2
        {
            public string Description { get; set; }
        }
    
        [ComVisible(true)]
        [Guid("2791082F-F505-49C4-8952-80C174E4FE96")]
        public interface ITestGateway
        {
            //MarshalAsAttribute is somewhat important, it tells the tlbexp.exe tool to mark
            // the comInputValue parameter as IUnknown* in the COM interface.
            //This is good because VARIANTS kinda suck...You'll see what I mean in the C++
            // side.  It also keeps some jack-wagon from passing a VARIANT_BOOL in
            // on your object parameter.
            void DoSomething(string a, [MarshalAs(UnmanagedType.Interface)]object comInputValue);
        }
    
        [ComVisible(true)]
        [Guid("C3D079F3-7869-4B3E-A742-263775C6EA63")]
        public class TestGateway : ITestGateway
        {
            public void DoSomething(string a, object comInputValue)
            {
                if (a == "yes")
                {
                    var entity = (TestEntity1)comInputValue;
                }
                else
                {
                    var entity = (TestEntity2) comInputValue;
                }
                //OR
    
                if(comInputValue is TestEntity1)
                {
                    //Do whatever here, and you don't need to test
                    // a string input value.
                }
                else if(comInputValue is TestEntity2)
                {
                    //Other stuff is done here.
                }
                else
                {
                    //Error condition??
                }
            }
        }
    }
    

    That can be called by the following C++:

    // ComClient.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #import <mscorlib.tlb> raw_interfaces_only
    
    //This creates the CLSID_ and IID_ constants, and
    // some strongly-typed interfaces.
    #import "..\Debug\ClassLibrary1.tlb" no_namespace named_guids
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        ITestGateway* test = NULL;
    
        char buffer[50];
        gets(buffer);  //Just a pause to attach the debugger in Managed + Native mode...hit enter in the console.
    
        CoInitialize(NULL);
    
        HRESULT hr = CoCreateInstance(CLSID_TestGateway,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_ITestGateway,
            reinterpret_cast<void**>(&test));
    
        if(FAILED(hr)) {
            printf("Couldn't create the instance!... 0x%x\n", hr);
            gets(buffer);
        } else {
            _bstr_t someString("yes");
    
            //Instead of fooling with CComVariant,
            // just directly create a TestEntity1...which COM will return
            // as an ITestEntity1.
            ITestEntity1* testEntity1 = NULL;
            HRESULT hr = CoCreateInstance(CLSID_TestEntity1,
                NULL,
                CLSCTX_INPROC_SERVER,
                IID_ITestEntity1,
                reinterpret_cast<void**>(&testEntity1));
    
            if(FAILED(hr)) {
                printf("Entity was not created!... 0x%x\n", hr);
                gets(buffer);
                return 0;
            }
    
            //Set some kind of property just for show.
            testEntity1->PutThing(VARIANT_FALSE);
    
    
    
            //If you attached your debugger with Managed code & Native code,
            // you should be able to hit a C# break point during this call.
            //Also, notice that there is no cast for testEntity1.  All interfaces
            // in COM derive from IUnknown, so you can just pass it.
            //IDispatch also derives from IUnknown, so if that's what you already have,
            // you can just pass it as well, with no cast.
            test->DoSomething(someString, testEntity1);
    
            printf("Something was done.");
    
            testEntity1->Release(); //Release anything you make through CoCreateInstance()
        }
    
        test->Release();
    
        return 0;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have the following interface which I'm trying to make COM-visible. When I try
I have created a .NET DLL which makes some methods COM visible. One method
We have a COM object implemented with C++/ATL that includes a method which will
I have a COM object written using the MS ATL library. I have declared
I have a COM interop assembly, and I would like to check from a
I have a COM SDK written in C++ and I'd like to create documentation
I have a VB6 COM component which I need to call from my .Net
I have an OLE COM object that trying to write a wrapper for, I
I have a COM dll written in vb6. When I try to create a
I have been using com.sun.org.apache.xpath.internal.XPathAPI for some time and it seems to work ok.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.