在C#中使用IClassFactory时出现InvalidCastException

时间:2012-01-30 11:10:20

标签: c# .net com interop com-interop

我试图在没有C#项目注册的情况下实例化ActiveX控件。我正在做以下事情:

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代码主要基于this文章,似乎可以与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生成的接口。我想避免使用附属程序集,因为我不能使它们使用无reg的COM,我们的部署需要这样做。抛出异常是什么?我使用的是与传统的卫星组装方式相同的指南。 guid没有正确编组吗?我怎样才能使它发挥作用?


为了完整起见:我设法完成了这个。我的方法是查看AxHost源代码(使用ILSpy)并查看创建实例时它的作用:

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

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

到目前为止,似乎工作正常。

1 个答案:

答案 0 :(得分:2)

你这里的Guid错了。 CreateInstance调用要求您传递接口IID,而不是coclass CLSID。请改用typeof(IMyControl).GUID。

下一个可能的失败模式是线程的公寓状态,最好是STA或COM要寻找可能不存在的代理。您正在绕过CLR所具有的安全防护装置,在需要时对接口指针进行编组。 从不使用错误线程中的对象。不太确定这是值得冒险的。