关于 com interop:Consuming COM-object from C# console-project

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 主题也可能为您提供很好的参考。