从C#console-project消耗COM对象 [英] Consuming COM-object from C# console-project

查看:189
本文介绍了从C#console-project消耗COM对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题从C#消费COM类。 COM类是在C ++ ATL 32位开发的。



当我使用VBA,VB6,C ++,Javascript甚至MSTest / C#



奇怪的是,当我从一个NUnit测试或从一个控制台应用程序创建一个实例时,它会失败,例外:

  System.InvalidCastException:无法将类型为PvtsFlashLib.FlashClass的COM对象转换为接口类型PvtsFlashLib.IFlash4。此操作失败,因为由于以下错误,COM组件上的QueryInterface调用与IID'{07065455-85CD-42C5-94FE-DDDC1B1A110F}'的接口失败:不支持此类接口(来自HRESULT的异常:0x80004002(E_NOINTERFACE)) 。有人能指出我的方向吗?











先感谢您的帮助。



test-project和控制台项目的生成配置设置为:

  Platform = x86 

COM参考在两个项目中设置为:

 复制Local = True 
嵌入Interop Types = False
Isolated = False

MSTest的代码适用于:

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

命名空间TestProject1
{
[TestClass]
public class TestOfCommsTest
{
[TestMethod]
public void CreateFlash
{
var flash = new Flash();
flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
}
}
}

NUnit测试失败的代码:

 使用NUnit.Framework; 
using PvtsFlashLib;

命名空间测试
{
[TestFixture]
public class TestOfComNUnit
{
[Test]
public void CreateFlash
{
var flash = new Flash();
flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
}
}
}

失败:

 使用PvtsFlashLib; 

命名空间ConsoleTest
{
类程序
{
static void Main(string [] args)
{
var flash = new Flash();
flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties;
}
}
}

信誉点回答我自己的问题。但是她无论如何:



由于某种原因,COM对象不能从MTAThread创建。 MSTest默认为STAThread和NUnit,控制台默认为MTAThread。应用[STAThread]属性到ConsoleTest.Main()和Test.CreateFlash()解决了这个问题。

解决方案

,问题是与COM对象运行在不同的公寓从您的.NET代码。鉴于观察,QueryInterface失败的最可能原因是目标接口不可跨公寓。这可能是COM中的一个问题,即使不涉及.NET。



您确实找到了最简单的解决方案,即确保您的.NET代码在STA中运行



但是,如果你的接口可以使用代理/存根封送器,你也可以使用MTA线程。由于您提到您正在使用ATL,因此您只需在应用程序设置



接口封送也可以为您提供一个很好的参考。


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.

解决方案

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.

这篇关于从C#console-project消耗COM对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆