从C#console-project中使用COM-object

时间:2012-01-11 22:39:55

标签: com com-interop

我在使用C#中的COM类时遇到问题。 COM类是用C ++ ATL 32位开发的。

当我使用VBA,VB6,C ++,Javascript甚至MSTest / C#时,COM-class工作正常#

奇怪的是,当我从NUnit-test或Console应用程序创建实例时,它失败并出现异常:

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)).

有人能指出我正确的方向吗?

提前感谢您的帮助。

测试项目和控制台项目的构建配置设置为:

Platform = x86

两个项目中的COM引用都设置为:

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

MSTest的代码工作正常:

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;
        }
    }
}

失败的NUnit测试代码:

using NUnit.Framework;
using PvtsFlashLib;

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

控制台应用的代码也失败了:

using PvtsFlashLib;

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

我没有足够的声望点来回答我自己的问题。但无论如何她就是这样:

由于某种原因,无法从MTAThread创建COM对象。 MSTest默认为STAThread,NUnit和Console默认为MTAThread。将[STAThread]属性应用于ConsoleTest.Main()和Test.CreateFlash()可以解决问题。

1 个答案:

答案 0 :(得分:1)

正如您所确定的那样,问题与在与.NET代码不同的公寓中运行的COM对象有关。鉴于该观察结果,QueryInterface失败的最可能原因是因为目标接口不能跨公寓进行编组。即使不涉及.NET,这也可能是COM中的问题。

您确实找到了最简单的解决方案,以确保您的.NET代码在STA线程中运行以匹配您的COM组件。

但是,如果您的接口可以使用代理/存根封送程序,您也可以使用MTA线程。由于您提到您正在使用ATL,因此您只需在Application Settings中设置“允许合并代理/存根代码”选项。

Interface Marshaling上的MSDN主题也可能为您提供很好的参考。