2012-01-11 61 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主題也可能爲您提供很好的參考。