我试图在 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
接口(interface)是aximp.exe/source
生成的接口(interface)。我想避免使用附属程序集,因为我不能让它们使用无注册的 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
私有(private)字段。该字段最初通过从 CreateInstance
调用 CoCreateInstance
获取值。然后我调用其他方法来修复其他连接(所有这些都是私有(private)的,所以再次反射)。如果该类未注册,则在构造函数中抛出异常(CoCreateInstance 失败),因此我在 finally block 中执行此操作。
到目前为止,它似乎工作正常。
最佳答案
您在这里弄错了 Guid。 CreateInstance 调用要求您传递接口(interface) IID,而不是组件类 CLSID。请改用 typeof(IMyControl).GUID。
下一个可能的大失败模式是线程的单元状态,最好是 STA 或 COM 正在寻找可能不存在的代理。您正在绕过 CLR 的安全防护措施,在需要时编码(marshal)接口(interface)指针。 永远不要使用来自错误线程的对象。不太确定这是否值得冒险。
关于c# - 在 C# 中使用 IClassFactory 时出现 InvalidCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9062910/