手动生成C#的COM包装类的常见问题和解决办法
来源:互联网 发布:99乘法表java代码 编辑:程序博客网 时间:2024/05/29 07:37
看一下如下代码:
[Guid("25088995-7924-4B15-B01A-EA7C422ADC68")]
public class CHelloClass : IHello
{
[DispId(1)]
[MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
public extern void HelloWorld();
}
class Program
{
static void Main(string[] args)
{
CHelloClass obj = new CHelloClass();
obj.HelloWorld();
}
}
这里的CHelloClass是一个COM对象,指定了GUID,实现了IHello接口的HelloWorld函数。然而,当执行这条语句CHelloClass obj = new CHelloClass,会产生如下异常:
Unhandled Exception: System.Security.SecurityException: ECall methods must be packaged into a system module.
这里异常信息需要解释一下:ECall是一种内部调用的方式(还存在其它方式如FCall等),由CLR本身实现,而不由用户提供实现。当CHelloClass中缺少ComImportAttrib这个属性的时候,CLR会认为HelloWorld这个函数是在CLR本身实现的,然后又在CLR内部的调用表(这个表维护所有CLR内部调用的函数)无法查到对应的实现,所以才抛出异常。当ComImportAttribute存在的时候,CLR才知道这个class是从COM对象Import过来的,从而作一些特殊处理,并不会对HelloWorld按照ECall方式来处理。
我们再看一下,是否MethodImplAttribute这里真正需要呢?可以试一下加上ComImport然后去掉MethodImplAttri看看:
[ComImport]
[Guid("25088995-7924-4B15-B01A-EA7C422ADC68")]
public class CHelloClass : IHello
{
[DispId(1)]
public extern void HelloWorld();
}
class Program
{
static void Main(string[] args)
{
CHelloClass obj = new CHelloClass();
obj.HelloWorld();
}
}
当到了new CHelloClass这条语句的时候,会产生下面异常:
Unhandled Exception: System.TypeLoadException: Could not load type 'CHelloClass' from assembly 'Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'HelloWorld' has no implementation (no RVA). at Program.Main(String[] args)
这一次,CLR则报告HelloWorld函数没有对应的实现代码。没有RVA的意思是CLR无法找到HelloWorld函数代码的位置。这个位置是一个内存的相对位置,因此称之为RVA(Relative Virtual Address)。由于实际的实现是由CLR提供,准确说是RCW提供,因此这里是需要MethodImplAttrbute的。
最终正确的版本如下:
[ComImport]
[Guid("25088995-7924-4B15-B01A-EA7C422ADC68")]
public class CHelloClass : IHello
{
[DispId(1)]
[MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
public extern void HelloWorld();
}
class Program
{
static void Main(string[] args)
{
CHelloClass obj = new CHelloClass();
obj.HelloWorld();
}
}
当然了,如果你不自己编写COM Wrapper代码的话则不会遇到类似的问题。所以请尽可能的让Tlbimp替你生成Interop代码,而不是自己手动编写,除非Tlbimpl生成的代码不符合你的要求。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1608022
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 手动生成C#的COM包装类的常见问题和解决办法
- 使用WinDbg对Windows Live Toolbar死锁的简单分析
- Visual Studio中的Class Designer设计工具需要您的建议!
- 微软在全国高校举办Silverlight大赛: http://www.msuniversity.edu.cn/static/silverlight/index.html
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- .NET / Rotor源码分析4 - 修改Rotor使其发送CLR Notification
- 手动生成C#的COM包装类的常见问题和解决办法
- .NET / Rotor源码研究3 – 调试Rotor托管代码的利器:WinDbg和SOS
- HashTab v2.0.7 Shell Extension
- IBM RAD简单使用
- Visual Studio 2005的JIT Debugger在Vista上面无法正常工作
- 我的MSDN Blog正式开张,欢迎大家访问 [ http://blogs.msdn.com/yizhang/ ]
- ACM UVa算法题209 Triangular Vertices的解法
- 另一道看上去很吓人的面试题:如何交换a和b两个整数的值,不用额外空间 (Rev. 2)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)