2012-01-11 104 views
3

我有一个从C#中使用COM类的问题。 COM类是用C++ ATL 32位开发的。从C#中使用COM对象console-project

的COM级工作正常,当我使用它从VBA,VB6,C++,JavaScript和甚至从MSTest的/ C#

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

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

我没有足够的信誉分,回答我的问题。但她无论如何:

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

回答

1

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

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

但是,如果您的接口可以使用代理/存根封送拆收器,您也可以使用MTA线程。既然你提到你在使用ATL,你可以简单地设置Application Settings中的“允许合并代理/存根代码”选项。

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