Consuming COM-object from C# console-project
我在使用 C# 中的 COM 类时遇到问题。 COM 类是用 C ATL 32 位开发的。
当我在 VBA、VB6、C、Javascript 甚至 MSTest/C# 中使用 COM 类时,它可以正常工作
奇怪的是,当我从 NUnit 测试或控制台应用程序创建实例时,它会失败并出现以下异常:
1 | 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)). |
有人能指出我正确的方向吗?
提前感谢您的帮助。
测试项目和控制台项目的构建配置设置为:
1 | Platform = x86 |
两个项目中的 COM 引用设置为:
1 2 3 | Copy Local = True Embed Interop Types = False Isolated = False |
运行良好的 MSTest 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 测试失败的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | using NUnit.Framework; using PvtsFlashLib; namespace Test { [TestFixture] public class TestOfComNUnit { [Test] public void CreateFlash() { var flash = new Flash(); flash.AdvancedOptions = PvtsFlashAdvancedOptionsEnum.AllProperties; } } } |
同样失败的控制台应用程序代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() 即可解决问题。
正如您所确定的,问题与在与您的 .NET 代码不同的单元中运行的 COM 对象有关。鉴于这一观察,QueryInterface 失败的最可能原因是目标接口不可跨单元编组。即使不涉及 .NET,这在 COM 中也可能是一个问题。
您确实找到了最简单的解决方案,即确保您的 .NET 代码在 STA 线程中运行以匹配您的 COM 组件。
但是,如果您的接口可以使用代理/Stubbing封送处理程序,您也可以使其与 MTA 线程一起使用。由于您提到您正在使用 ATL,您可以简单地在应用程序设置中设置"允许合并代理/Stubbing代码"选项。
Interface Marshaling 上的 MSDN 主题也可能为您提供很好的参考。