C#生成COM接口及注意事项(含注册脚本)
- 编写实现,注意实现类上必须有 [ClassInterface(ClassInterfaceType.None)] 特性
using System.Runtime.InteropServices; namespace EcgTool { public interface IEcgBaseUtility { bool DecompressData(byte[] compressbuffer,ref short[] _decompressData); } [ClassInterface(ClassInterfaceType.None)] public class EcgTools : IEcgBaseUtility { public bool DecompressData(byte[] compressbuffer,ref short[] _decompressData) { EcgBaseUtilityWrap.EcgBaseUtilityWrap ecgBaseUtilityWrap = new EcgBaseUtilityWrap.EcgBaseUtilityWrap(); var ret = ecgBaseUtilityWrap.DecompressData(compressbuffer,_decompressData, 1); return ret; } } }
- 修改Properties下面的AssemblyInfo.cs
[assembly: ComVisible(true)] [assembly: ClassInterface(ClassInterfaceType.AutoDual)]
- 点开 项目-项目属性-生成 找到"为COM互操作注册" 勾选保存
以上就是基于VS2019生成COM的操作。
需要注意的是如果需要带出参数,需要在参数前加上 ref (和是否是引用类型无关)。如上面的 _decompressData
实际实现ecgBaseUtilityWrap.DecompressData中是没有ref的,为什么我们自己声明的COM函数需要加?
可以参考: C#程序员请不要混淆引用类型和ref引用传参
如果觉得上面绕,可以参考我的理解:
COM是win系统给的接口,你写的dll和调用者exe中间的数据是通过系统传递的,上面的数组在系统中实际是一个PSafeArray
而不是C#中的byte[]和short[]。即我们的参数a被一个b的参数接收了,里面实际操作的是b(是不是回想起形参和实参的区别?)
所以这样数据是带不出来的,而我们解决形参值带不出来的办法就是加个ref。
本机调试因为步骤3所以是不需要注册的,但当我们把dll给用户时,用户需要注册才能调用COM的dll。
@echo off if not "%OS%"=="Windows_NT" exit if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0 bcdedit >nul if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin) :UACPrompt %1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit exit /B :UACAdmin echo 已获取管理员权限 ::获取当前路径 注册需要编写dll对应的.net版本 防止使用默认的RegAsm.exe cd /d "%~dp0" set path=%cd% echo 当前路径:%path% ::先取消注册 再注册 %path%\RegAsm.exe /u %path%\EcgTool.dll %path%\RegAsm.exe %path%\EcgTool.dll echo 按任意键退出 pause >nul exit
把.net对应的RegAsm.exe版本和动态库放在同一目录,
将上面的脚本保存成.bat文件运行即可。ps:记得把 EcgTool.dll 改为自己的dll

浙公网安备 33010602011771号