Consuming COM-object from C# console-project

2019-07-03 16:19发布

I have a problem consuming a COM-class from C#. The COM-class is developed in C++ ATL 32-bit.

The COM-class works fine when i use it from VBA, VB6, C++, Javascript and even from MSTest/C#

The wierd thing is that when i create an instance from a NUnit-test or from a Console application it fails with the exception:

System.InvalidCastException : Unable to cast COM object of type 'PvtsFlashLib.FlashClass' to interface type 'PvtsFlashLib.IFlash4'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{07065455-85CD-42C5-94FE-DDDC1B1A110F}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

Can someone point me in the right direction?

Thanks in advance for your help.

The build config for the test-project and the console project is set to:

Platform = x86

The COM reference in both projects is set to:

Copy Local = True
Embed Interop Types = False
Isolated = False

Code for MSTest that works fine:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using PvtsFlashLib;

namespace TestProject1
{
    [TestClass]
    public class TestOfComMSTest
    {
        [TestMethod]
        public void CreateFlash()
        {
            var flash = new Flash();
            flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
        }
    }
}

Code for NUnit test that fails:

using NUnit.Framework;
using PvtsFlashLib;

namespace Test
{
    [TestFixture]
    public class TestOfComNUnit
    {
        [Test]
        public void CreateFlash()
        {
            var flash = new Flash();
            flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
        }
    }
}

Code for Console app that also fails:

using PvtsFlashLib;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var flash = new Flash();
            flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
        }
    }
}

I haven't got enough reputation points to answer my own question. But her it is anyway:

For some reason the COM-object can't be created from an MTAThread. MSTest defaults to STAThread and NUnit and Console defaults to MTAThread. Applying the [STAThread] attribute to ConsoleTest.Main() and Test.CreateFlash() solves the problem.

1条回答
可以哭但决不认输i
2楼-- · 2019-07-03 17:15

As you determined, the problem was related to the COM object running in a different apartment from your .NET code. Given that observation, the most likely reason that QueryInterface failed is because the target interface is not marshalable across apartments. This can be a problem in COM even when .NET is not involved.

You did find the simplest solution which is to ensure that your .NET code is running in an STA thread to match your COM component.

However, you can also get this to work with MTA threads if your interface can use a proxy/stub marshaler. Since you mentioned that you're using ATL, you can simply set the "Allow merging of proxy/stub code" option in the Application Settings.

The MSDN topic on Interface Marshaling might provide a good reference for you as well.

查看更多
登录 后发表回答