我在使用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()可以解决问题。
答案 0 :(得分:1)
正如您所确定的那样,问题与在与.NET代码不同的公寓中运行的COM对象有关。鉴于该观察结果,QueryInterface失败的最可能原因是因为目标接口不能跨公寓进行编组。即使不涉及.NET,这也可能是COM中的问题。
您确实找到了最简单的解决方案,以确保您的.NET代码在STA线程中运行以匹配您的COM组件。
但是,如果您的接口可以使用代理/存根封送程序,您也可以使用MTA线程。由于您提到您正在使用ATL,因此您只需在Application Settings中设置“允许合并代理/存根代码”选项。
Interface Marshaling上的MSDN主题也可能为您提供很好的参考。