手动生成C#的COM包装类的常见问题和解决办法

news/2025/1/25 21:18:42

看一下如下代码:

    [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函数代码的位置。这个位置是一个内存的相对位置,因此称之为RVARelative 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生成的代码不符合你的要求。

 



https://dhexx.cn/news/show-3785807.html

相关文章

丰收节拍丰收中奖 农村淘宝给一家全年管饭

“天哪!这么多,这真的一年估计都吃不完” 尽管早有心理准备,但当王宏旻面对农村淘宝送的整整1200斤大米时,仍不禁感叹。 农村淘宝推出共享丰收喜悦“随手拍丰收”活动。一周时间内全国32个省市区上万名网友参与,随手拍…

阿里CEO张勇:不存在阿里巴巴模式,我们一直在高速演进

双节期间,马云在联合国"加班",阿里CEO张勇也没闲着。 昨天,即将于明年接任阿里巴巴集团董事局主席的张勇,参加了2018安永全球新晋合伙人大会,并发表了精彩的演说,"不存在阿里巴巴模式&…

Visual Studio 2005的JIT Debugger在Vista上面无法正常工作

Visual Studio 2005的Jit Debugger在Vista上不工作,即使你打了SP1和Update for Windows Vista也不行。修改Jit Debugger使其工作在Vista上需要大量的修改,因此这个工作被移到Visual Studio Code Name Orcas,也就是2007中去了。不过不排除微软…

抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单

原文:抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Vblegend_2013/article/details/83447420 源码已封装成 MirrorGrid类 可以直接在XAML里添加 根据需要可以把Grid 改…

黄金周未来景区游客涨6倍 阿里巴巴数字经济体引领体验式消费升级

免排队、秒刷脸、轻松反复入园……国庆假期前两日,西溪湿地未来景区游客数量达到平日的6倍,每天有上千位游客享受"无需取票、不刷身份证"的"纯刷脸"极致入园体验。 这就是阿里巴巴旗下旅行品牌飞猪通过技术创新和大数据赋能景区的一…

ACM UVa算法题209 Triangular Vertices的解法

有一段时间没有做ACM算法题目了,今天正好有空便随便挑了209题来做做:ACM UVa算法题#209题这道题有几个要点:1. 给定坐标系坐标系很容易定,我采用的是第一个点为(0, 0)点,X方向差别为2个单位,Y方向差别为1…

Java复习笔记(三)

程序控制语句if条件语句只要满足条件就处理,不完全是顺序结构,可以跳着执行。(1)if (条件语句){执行语句;}else{执行语句;}(2)if ....else if....elseif (条件1){执行语句}else if …

我的MSDN Blog正式开张,欢迎大家访问 [ http://blogs.msdn.com/yizhang/ ]

我的MSDN Blog创建了其实有一阵子了,但是一直没有时间添加内容。这两天写了几篇文章(新的和在CSDN Blog上面发表过的,内容比较简单)放在上面。这个Blog主要是英文的内容,主要会和我在Microsoft的所进行的CLR开发工作有关系&#x…

CentOS下SELinux安全设置

2019独角兽企业重金招聘Python工程师标准>>> CentOS下SELinux安全设置 centos 系统安全防御 2017年12月14日 529 0 0 一、SELinux配置文件 在CentOS 7系统中部署SELinux非常简单,由于SELinux已经作为模块集成到内核中,默认SELinux已经处于激活…