我在 dll 中有这个接口(这个代码显示在元数据的 Visual Studio 中):
#region Assembly XCapture.dll, v2.0.50727
// d:\svn\dashboard\trunk\Source\MockDiagnosticsServer\lib\XCapture.dll
#endregion
using System;
using System.Runtime.InteropServices;
namespace XCapture
{
[TypeLibType(4160)]
[Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
public interface IDiagnostics
{
[DispId(1)]
void GetStatusInfo(int index, ref object data);
}
}
所以我用这样的类创建了一个 COM 服务器:
[ComVisible(true)]
[Guid(SimpleDiagnosticsMock.CLSID)]
[ComDefaultInterface(typeof(IDiagnostics))]
[ClassInterface(ClassInterfaceType.None)]
public class SimpleDiagnosticsMock : ReferenceCountedObject, IDiagnostics
{
public const string CLSID = "281C897B-A81F-4C61-8472-79B61B99A6BC";
// These routines perform the additional COM registration needed by
// the service. ---- stripped from example
void IDiagnostics.GetStatusInfo(int index, ref object data)
{
Log.Info("GetStatusInfo called with index={0}, data={1}", index, data);
data = index.ToString();
}
}
服务器似乎工作正常,我可以使用 VBScript 中的对象。但后来我尝试从另一个 C# 客户端使用它:
[STAThread]
static void Main(string[] args)
{
Guid mockClsId = new Guid("281C897B-A81F-4C61-8472-79B61B99A6BC");
Type mockType = Type.GetTypeFromCLSID(mockClsId, true);
IDiagnostics mock = (IDiagnostics)Activator.CreateInstance(mockType);
//var diag = mock as IDiagnostics;
object s = null;
mock.GetStatusInfo(3, ref s);
Console.WriteLine(s);
Console.ReadKey();
}
它失败了
无法将“System.__ComObject”类型的 COM 对象转换为接口类型“XCapture.IDiagnostics”。此操作失败,因为 IID 为“{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}”的接口的 COM 组件上的 QueryInterface 调用失败,原因是以下错误:不支持此类接口(来自 HRESULT 的异常:0x80004002 (E_NOINTERFACE)) .
我究竟做错了什么?
我也尝试过使用 InvokeMember,除了我无法获得 ref-returned data参数之外,这有点工作。
编辑:将 STAThread 属性添加到我的 Main 过程中。这并不能解决问题,但是除非您绝对确定不需要它,否则您确实应该将 STAThread 与 COM 一起使用。请参阅下面的 Hans Passant 的回答。