标题: [原创] 如何制作com组件 [打印本页]
作者: jyswjjgdwtdtj 时间: 2024-7-12 15:01 标题: 如何制作com组件
本帖最后由 jyswjjgdwtdtj 于 2024-7-15 16:39 编辑
受制于微软对vbs安全性的考量 vbs只能使用com组件与电脑交互
远古时期有人很喜欢用vb6制作com vb6对于com极其支持 你甚至可以不用写出class的关键字
而用c++等底层语言则工作量就较为恐怖 借口等等均要手动实现
那如何创建com组件呢?
所需材料:一台安装有.net framework(win7及以上基本均有安装)的windows电脑 无需visual studio
编写com组件使用vb.net语言
需要明确一点,vbs是一项基于com组件的语言,换句话说vbs中的任何一个对象均为com对象,且vbs只支持符合com规范的对象。若你将vbs中声明的类对象传入.net .net会告诉你那是System.__ComObject
类型 所以请勿将.net中的对象直接返回至vbs,vbs不支持的泛型,枚举等等会使对象不可用
首先介绍一下vb.net
vbs作为vb家族的一员,在语法上基本是vb6的真子集。而在vb.net中,为了适应更现代化的面向对象,vb.net添加了接口,继承等等内容,同时对于类的结构做出了调整
vb.net的程序结构为- namespace vbnamespace '命名空间
- module vbmodule '模块 可以直接理解为静态类
- class vbclass '类
- public a as string'变量
- public sub new()'构造函数
- end sub
- public property ppt
- get
- end get
- set
- end set
- end property
- end class
- end module
- end namespace
复制代码
有兴趣可以自行学习(但似乎c#远更为流行
编写com组件首先需要引入命名空间,可以理解为载入别人写好的函数
准备好程序内容所在的namespace namespace名字为com组件progid的前半部分
这一部分可以无脑照抄- Imports System
- Imports System.Runtime.InteropServices
-
- Namespace progid_NamespaceName
-
-
- End Namespace
复制代码
添加一个接口
为它打上标签- Imports System
- Imports System.Runtime.InteropServices
-
- Namespace progid_NamespaceName
- <ComVisible(True)>
- <Guid("yourguid")>'guid可以用工具生成
- <InterfaceType(ComInterfaceType.InterfaceIsDual)>
- Public Interface IComExample
- '这里写入函数声明 如
- '每个函数 变量均必须在接口中声明 否则不能被外部使用
- Function tostring(obj as object) As string
- Public strname as string
- 'Sub mysub(abc As paramtype) As returntype
- End Interface
- End Namespace
复制代码
然后制作com对象
com对象的主体部分为一个类- Public Class progid_ClassName
- '必将其设置为public 名字为progid的后半部分
- Implements IComExample'继承接口 必须要加
- Public Function tostring(obj as object) As string Implements IComExample.tostring
- '实现接口中的函数 implements语句代表着这个函数是接口中的函数
- Return Convert.ToString(obj)
- '相当于
- 'tostring=Convert.ToString(obj)
- 'exit function
- End Function
- Public str as string="string"
- End Class
复制代码
只有继承了接口的类可以被外部创建
将主体对象添加进- Imports System
- Imports System.Runtime.InteropServices
-
- Namespace vbcom
- <ComVisible(True)>
- <Guid("00000000-0000-0000-0000-000000000000")>
- <ClassInterface(ClassInterfaceType.None)>
- Public Interface IComExample
- Function tostring(obj as object) As string
- End Interface
-
- '也给对象打上标签 guid不能一样
- <ComVisible(True)>
- <Guid("11451419-1981-0114-5141-919810000000")>'注意 与接口中的不一样
- <InterfaceType(ComInterfaceType.InterfaceIsDual)>
- <ProgId(mynewcom.test))>'progid标签可以强制类的progid
- Public Class ComExample
- Implements IComExample
- Public Function tostring(obj as object) As string Implements IComExample.tostring
- Return Convert.ToString(obj)
- End Function
- End Class
- End Namespace
复制代码
这是一个clsid为{11451419-1981-0114-5141-919810000000} progid为vbcom.comexample的com组件 包含一个名为tostring的函数 可以将对象转换为字符串
代码编写完成后 将其保存为mycom.vb 接下来进行编译
找到C:\Windows\Microsoft.NET\中版本最新的vbc.exe 用它的路径替换以下路径 或直接使用
建议在编译时使用绝对路径 并将dll保存至system32文件夹- ::bat
- "C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /target:library /out:C:\mycom.dll /platform:anycpu C:\mycom.vb
复制代码
将mycom.vb编译为mycom.dll- C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /u C:\mycom.dll
- C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe C:\mycom.dll /codebase
复制代码
卸载;加载 注意:这一步要管理员权限 请用管理员运行bat
如果你想要修改你的com组件 无需重新使用regasm注册 只需用新的com组件dll将原本的替代掉即可
如果任何一个步骤没有报错 那com组件就可以用了- set myfirstcom=createobject("vbcom.comexample")
- msgbox myfirstcom.tostring(123)
复制代码
然后你就可以制作属于自己的com组件了!
可以在同一个命名空间下有多个com类 可以重复interface-class一一对应
作者: buyiyang 时间: 2024-7-12 20:01
感谢详尽的分享!
可能有笔误,第一段代码接口和类的类型说明写反了哦,第二段代码类没有绑定接口实现
作者: czjt1234 时间: 2024-7-12 21:39
不明觉厉 .
作者: jyswjjgdwtdtj 时间: 2024-7-13 12:01
回复 2# buyiyang
第一段已改正 第二段没错呀 没有继承接口的类不公开给com组件
作者: Five66 时间: 2024-7-13 12:02
用.net支持的语言写com确实简单多了
不过写出来的com貌似是基于clr的
还有调第三方是神,都来调第三方吧
作者: jyswjjgdwtdtj 时间: 2024-7-15 16:38
回复 5# Five66
是的 速度慢
还有自己做第三方给自己用和调别人的第三方还是有点区别的吧
作者: Five66 时间: 2024-7-19 22:22
回复 6# jyswjjgdwtdtj
自己做第三方给自己用,一般都会力求简单吧, 甚至可能全程在其里面实现,直接运行即可
作者: jyswjjgdwtdtj 时间: 2024-7-20 16:50
回复 7# Five66
其实对于.net里的语言 不如就把他当成一种脚本来使用
powershell实在接受不了
作者: jyswjjgdwtdtj 时间: 2024-8-5 17:06
发个例子- using System.Runtime.InteropServices;
- using System.Windows.Forms;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
-
- namespace VBScript
- {
- [ComVisible(true)]
- [Guid("FD3B7777-90F5-AC77-C8D3-1B5259B42927")]
- [InterfaceType(ComInterfaceType.InterfaceIsDual)]
- public interface IWinForm
- {
- Control GetControl(string controlname);
- void AddControl(object c, object p);
- void AddControl(object c, object[] p);
- Control[] GetControlList(object c);
- void AttachEvent(object c, string eventname, object f);
- }
-
- [ComVisible(true)]
- [Guid("2A0C7DB1-4CAF-561D-130A-2C52DB0DF12D")]
- [ClassInterface(ClassInterfaceType.None)]
- public class WinForm : IWinForm
- {
- public Control GetControl(string controlname)
- {
- return (Control)typeof(System.Windows.Forms.Form).Assembly.CreateInstance("System.Windows.Forms." + controlname, true);
- }
- public void AddControl(object c, object p)
- {
- ((Control)c).AddControl((Control)p);
- }
- public void AddControl(object c, object[] p)
- {
- ((Control)c).AddControl(p);
- }
- public Control[] GetControlList(object c)
- {
- return ((Control)c).GetControlList();
- }
- public void AttachEvent(object c, string eventname, object f)
- {
- ((Control)c).AttachEvent(eventname, f);
- }
- }
-
- public static class ExtensionMethodForWinFormInCom
- {
- public static Control[] GetControlList(this Control control)
- {
- IList<Control> list = (IList<Control>)control.Controls;
- return list.ToArray();
- }
- public static void AddControl(this Control p, Control c)
- {
- p.Controls.Add(c);
- }
- public static void AddControl(this Control p, object[] c)
- {
- List<Control> cl = new List<Control>();
- Type ctlt = typeof(Control);
- foreach (object o in c)
- {
- if (o.GetType() == ctlt)
- {
- cl.Add(o as Control);
- }
- }
- p.Controls.AddRange(cl.ToArray());
- }
- public static void AttachEvent(this Control c, string eventname, object co)
- {
- EventInfo ev = c.GetType().GetEvent(eventname);
- switch (ev.EventHandlerType.Name)
- {
- case "KeyEventHandler":
- ev.AddEventHandler(c, new KeyEventHandler((object sender, KeyEventArgs e) =>
- {
- ComFuncCaller.Invoke(co, sender, e);
- }));
- break;
- case "KeyPressEventHandler":
- ev.AddEventHandler(c, new KeyPressEventHandler((object sender, KeyPressEventArgs e) =>
- {
- ComFuncCaller.Invoke(co, sender, e);
- }));
- break;
- case "MouseEventHandler":
- ev.AddEventHandler(c, new MouseEventHandler((object sender, MouseEventArgs e) =>
- {
- ComFuncCaller.Invoke(co, sender, e);
- }));
- break;
- case "EventHandler":
- ev.AddEventHandler(c, new EventHandler((object sender, EventArgs e) =>
- {
- ComFuncCaller.Invoke(co, sender, e);
- }));
- break;
- case "PaintEventHandler":
- ev.AddEventHandler(c, new PaintEventHandler((object sender, PaintEventArgs e) =>
- {
- ComFuncCaller.Invoke(co, sender, e);
- }));
- break;
- default:
- break;
- }
- }
- public static class ComFuncCaller
- {
- public static void Invoke(dynamic o,object sender,dynamic e)
- {
- (new z(o)).zz(sender,e);
- }
- private struct z
- {
- public dynamic zz;
- public z(dynamic zzz)
- {
- zz = zzz;
- }
- }
- }
- }
- }
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |