在C#中使用IClassFactory时出现InvalidCastException

本文关键字:InvalidCastException IClassFactory | 更新日期: 2023-09-27 18:21:56

我正在尝试实例化一个ActiveX控件,而不在C#项目中注册。我正在做以下事情:

Guid guid = new Guid("(guid of my control here)");
var classFactory = ComHelper.GetClassFactoryFromDll("mycontrol.ocx", guid);
if (classFactory != null)
{
    object obj;
    classFactory.CreateInstance(null, ref guid, out obj); // getting the exception here
    if (obj != null) ocx = (obj as IMyControl);
}

ComHelper代码主要基于本文,并且似乎可以很好地与IFilter示例配合使用。

这是我为IClassFactory编写的互操作代码:

    [ComVisible(false)]
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000001-0000-0000-C000-000000000046")]
    public interface IClassFactory
    {
        void CreateInstance([MarshalAs(UnmanagedType.Interface)] object pUnkOuter, ref Guid refiid,
                            [MarshalAs(UnmanagedType.Interface)] out object ppunk);
        void LockServer(bool fLock);
    }

IMyControl接口是aximp.exe /source生成的接口。我想避免使用附属程序集,因为我不能让它们使用无注册COM,而我们的部署需要这样做。是什么引发了异常?我使用的是与传统卫星组装方式相同的guid。guid是否整理不正确?我怎样才能让它工作?


为了完整起见:我设法做到了。我的方法是查看AxHost源代码(使用ILSpy),看看它在创建实例时会做什么:

private object GetOcxCreate()
{
    if (this.instance == null)
    {
        this.CreateInstance();
        this.RealizeStyles();
        this.AttachInterfaces();
        this.oleSite.OnOcxCreate();
    }
    return this.instance;
}

然后,我创建了生成的AxMyControl类的一个实例,并通过反射替换了instance私有字段。该字段最初通过从CreateInstance调用CoCreateInstance来获得一个值。然后我调用了其他方法来修复其他连接(所有这些方法都是私有的,所以还是反射)。如果该类没有注册,则会在构造函数中引发异常(CoCreateInstance失败),因此我在finally块中执行此机制。

到目前为止,它似乎运行良好。

在C#中使用IClassFactory时出现InvalidCastException

此处的Guid错误。CreateInstance调用要求您传递接口IID,而不是coclass CLSID。请改用(IMyControl)GUID的类型。

下一个可能的大故障模式是线程的单元状态,最好是STA或COM正在寻找一个可能不存在的代理。您正在绕过CLR的安全保护,在需要时封送接口指针永远不要使用来自错误线程的对象。不太确定这是否值得冒险。

相关文章:
  • 没有找到相关文章