2011-04-14 50 views
9

在我的节目我用COM +后期绑定C#4.0

Type comObjectType = Type.GetTypeFromProgID(progId, true); 
object comObject = Activator.CreateInstance(comObjectType); 

,然后使用反射调用的方法之一创建COM +对象动态地(后期绑定)

object result = comObjectType.InvokeMember(MethodToActivate, BindingFlags.InvokeMethod, null, comObjec, new object[] {....}); 

它的工作原理马丽娟在.net 1.1/2.0/3.5

现在我试图在为.NET 4.0编译的同一台计算机(Windows XP)上运行相同的代码,但我有一个

Exception: Method 'System.__ComObject.{MethodName}' not found. 

我对大多数Com +对象(不是所有)都有例外。 有谁知道这是什么问题? 为什么我在FW 4.0环境中遇到异常? 我该怎么做才能避免它?

非常感谢, 丹尼尔

经过一番详细的调查我发现,一些COM +代理为System._ComObject(这些都是原生的,我想),有的为System.Runtime.Remoting.Proxies._TransparentProxy创建创建(我认为那些是.Net Com +对象)。方法调用适用于创建为System._ComObject而不适用于System.Runtime.Remoting.Proxies._TransparentProxy的那些调用。 最有趣的事实是,在.Net 2.0中,所有对象都以相同的方式创建(_ComObject_TransparentProxy),但方法调用确实工作正常。 另一个有趣的事实是,我可以用几点思考

((System.EnterpriseServices.RemoteServicedComponentProxy)((((System.Runtime.Remoting.Proxies.__TransparentProxy)(ObjectToActivate)))._rp)).ProxiedType.GetMethods()

我想对于一些时刻,它可能是一个安全问题看在调试器中“失踪”的方法,但我运行代码WindowsService登录作为具有管理员权限的用户

+0

您是否检查过任何32/64位问题?也许你的程序是64位的,因此打到64位COM注册表(没有人住:-)? – 2011-04-27 06:17:03

+0

我不认为这是一个32/34位的问题,我的本地机器是32位,远程服务器 – 2011-04-27 07:14:53

+0

对32/64位也是如此。现在,它看起来像你的COM服务器不在进程中或具有特定的线程模型(因此代理)。你能提供更多细节吗?他们托管在过程之外吗?在组件服务中?那么Invoke参数呢?你确定没有歧义吗?那BindingFlags呢?你不需要Public | Instance吗? – 2011-04-27 07:49:12

回答

6

我发现COM类型创建中的.NET FW存在差异,并且据我了解,只有.NET COM对象存在差异。当COM对象类型是与

Type comObjectType = Type.GetTypeFromProgID(progId, true); 

时返回在.NET 1.1/2.0/3.5为对象的实际.NET类型,所以在它的方法调用没有问题,但在类型创建.NET 4.0 System.__ComObject类型返回所以代码

result = comObjectType.InvokeMember(
    MethodToActivate, BindingFlags.InvokeMethod, null, ObjectToActivate, InputParams); 

失败,未发现异常的方法。

,我已经找到了解决办法如下:

Type comObjectType = Type.GetTypeFromProgID(progId, true);   
object comObject = Activator.CreateInstance(comObjectType); 

// here the real object type is returned 
Type acctualObjectType = comObject.GetType(); 
result = acctualObjectType.InvokeMember(
    "MethodToActivate", BindingFlags.InvokeMethod, null, comObject, InputParams); 

此代码工作正常适用于所有环境。

+0

有趣的 - 我实际上发布了一个答案,以前我怀疑会有帮助的讽刺删除它后阅读另一个问题,说服我我错了! - 无论如何,很高兴你的问题得到了解决。 – Justin 2011-04-27 11:38:02

+0

在你的解决方案代码中,comObject应该和ObjectToActivate是一样吗? – 2014-09-12 20:43:46

+0

是的,ObjectToActivate是一个返回comObject的属性。 – 2014-09-13 21:42:29

1

我不确定为什么您的以前运行的代码不再有效,但我相信在.Net 4.0中,您可以使用IDispatch /后期绑定通过dynamic类型调用COM方法 - 请参阅Does C# .NET support IDispatch late binding?

+0

我想过这种解决方案,但它是不能接受的对我来说,因为我需要为所有.Net FW版本运行相同的代码。它是运行在不同环境中的核心库的一部分 – 2011-04-27 07:18:27

+0

@Daniel:不管它是否令人满意,是否使用'dynamic'仍显示错误? – Gabe 2011-04-27 08:27:34

+0

我尝试了一个与'动态'样本,它的工作原理(但对我来说无用(:) – 2011-04-27 08:28:49