开发环境为VS 2005, .NET framework 2.0
文件—>新建—>项目
弹出下面对话框

选择Windows 控件库 输入名称TestControl 点击“确定”
在设计窗口中拖入控件 label1 timer 2个button 如下图:

1. COM的接口和类创建
COM 接口(Interface):IMonitor

Code
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.ComponentModel;
5
using System.Runtime.InteropServices;
6
7
namespace TestControl
8

{
9
[
10
Guid("b505d5bb-2318-4fc9-8e91-6346cdd6fc91"),
11
InterfaceType(ComInterfaceType.InterfaceIsDual),
12
ComVisible(true)
13
]
14
public interface IMonitor
15
{
16
void LoadControl(string sClassroom);
17
void UnloadControl();
18
}
19
}
20
COM 类(Class):Monitor

Code
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Drawing;
5
using System.Data;
6
using System.Text;
7
using System.Windows.Forms;
8
using System.Runtime.InteropServices;
9
10
namespace TestControl
11

{
12
[
13
Guid("b505d5bb-2318-4fc9-8e91-6346cdd6fc91"),
14
ProgId("TestControl.Monitor"),
15
ClassInterface(ClassInterfaceType.None),
16
ComDefaultInterface(typeof(IMonitor)),
17
ComVisible(true)
18
]
19
public partial class Monitor : UserControl,IMonitor, IObjectSafety
20
{
21
public Monitor()
22
{
23
InitializeComponent();
24
}
25
26
public void LoadControl(string msg)
27
{
28
if (timer.Enabled == false)
29
{
30
timer.Start();
31
}
32
}
33
public void UnloadControl()
34
{
35
if (timer.Enabled == true)
36
{
37
timer.Stop();
38
}
39
}
40
41
private void timer_Tick(object sender, EventArgs e)
42
{
43
label1.Text = DateTime.Now.ToString();
44
}
45
46
47
private void Monitor_Load(object sender, EventArgs e)
48
{
49
50
}
51
52
private void button1_Click(object sender, EventArgs e)
53
{
54
timer.Enabled = true;
55
LoadControl("开始计时");
56
}
57
58
private void button2_Click(object sender, EventArgs e)
59
{
60
timer.Enabled = false;
61
UnloadControl();
62
}
63
}
64
}
1)GUID 指定该类或者接口的GUID。
2)声明属性InterfaceType(ComInterfaceType.InterfaceIsDual),ComVisible(true),以支持register 和 unregister。
3) IMonitor 是COM interface。C# 的COM Class 可以继承自COM interface 也可以不用interface.
2 实现IObjectSafety 接口
微软IObjectSafety 接口定义, GUID 为固定值, 一般不要修改,也可以重新生成GUID 在菜单栏 工具—>创建GUID
声明:
ObjectSafety

Code
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Runtime.InteropServices;
5
6
namespace TestControl
7

{
8
[
9
Serializable,
10
ComVisible(true)
11
]
12
public enum ObjectSafetyOptions
13
{
14
INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
15
INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
16
INTERFACE_USES_DISPEX = 0x00000004,
17
INTERFACE_USES_SECURITY_MANAGER = 0x00000008
18
};
19
20
//
21
// MS IObjectSafety Interface definition
22
//
23
[
24
ComImport(),
25
Guid("b505d5bb-2318-4fc9-8e91-6346cdd6fc91"),
26
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
27
]
28
public interface IObjectSafety
29
{
30
[PreserveSig]
31
long GetInterfaceSafetyOptions(ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions);
32
33
[PreserveSig]
34
long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions);
35
};
36
}
37
Monitor实现:

Code
1
[IObjectSafety implementation]#region [IObjectSafety implementation]
2
private ObjectSafetyOptions m_options = ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER |
3
ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA;
4
5
public long GetInterfaceSafetyOptions(ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions)
6
{
7
pdwSupportedOptions = (int)m_options;
8
pdwEnabledOptions = (int)m_options;
9
return 0;
10
}
11
12
public long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions)
13
{
14
return 0;
15
}
16
#endregion
IObjectSafety 是一个接口,它可将其功能显露给 Internet Explorer的“设置脚本安全性”和“设置初始化安全性”安全特性。
3.注册和卸载
如果Class 声明中使用了 InterfaceType ,ComVisible(true) 属性,并且项目属性页设置 点击“生产”的 “为COM interop 注册” 项为TRUE,那么VS编译该项目可自动为Class注册。
也可以使用VS2005 自带工具 regasm.exe 手动注册和卸载 Class,可以用VS 自带工具oleview 查看是否注册成功

4.测试 以及调试
1)创建测试页面 解决方案右键 添加—>新建网站 Default.aspx

Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
<script language="javascript">
function LoadControl()

{
if (document.all.Monitor.object != null)
document.all.Monitor.LoadControl();
}
function UnloadControl()

{
if (document.all.Monitor.object != null)
document.all.Monitor.UnloadControl();
}
</script>
</head>


<body onload="javascript:LoadControl()" onunload = "javascript:UnloadControl()" >
<form id="form1" runat="server">
<div id="DIV1">
<br />
<object id="Monitor" classid="clsid:b505d5bb-2318-4fc9-8e91-6346cdd6fc91" codebase="http://10.122.89.28/testreg/TestControl.cab" Width="640" Height="360">
</object>
</div>
</form>
</body>
</html>

2)将测试页面拷贝到localhost 的根目录(安装IIS,设置TestControl根目录 IIS配置详细步骤略过)
3) 可以开始调试
5.发布
1)建立一个windows安装项目,并将ActiveX控件的主输出添加到项目中。然后,改动ActiveX控件的主输出文件的属性,将其Register属性改为vsdrpCOM.

2)编译该项目并得到MSI 安装文件 ClassroomViewerControl.msi
3)创建并编写INF 文件 ClassroomViewerControl.inf

Code
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
hook1=hook1
[hook1]

run=msiexec.exe /i "%EXTRACT_DIR%\ClassroomViewerControl.msi" /qn

4) 创建CAB 文件 使用CAB SDK 中的工具CABARC.EXE (下载地址 http://support.microsoft.com/kb/310618)
CABARC.EXE -s 6144 n ClassroomViewerControl.cab ClassroomViewerControl.msi ClassroomViewerControl.inf
-s 6144:为签名留下6k的空间 n 创建cab
5) 签名,col.pfx 为密钥
signtool sign /f col.pfx ClassroomViewerControl.cab
6) 修改WEB PAGE hello.html并将CAB 拷贝到codebase指定的URL
<object id="Monitor" classid="clsid:627AD403-FA50-4a08-B875-770520865DD6" Width="640" Height="360" codebase="http://localhost/TestControl/ClassroomViewerControl.cab"> </object>
6.最后看一下效果
安装隐藏了msi 安装界面,类似于cabarc 打包ocx 的效果(点击install 之后其他的都后台做了)
注意:IE中没有弹出.cab安装窗口 如下图:

这就需要设置IE的安全选项
IE浏览器里的 工具—>Internet 选项—>安全

点击“自定义级别” 弹出下列窗口

将ActiveX 控件和插件的相关选项都启用 点击“确定”
再次测试 如果弹出“Windows已经阻止此软件因为无法验证发行者”提示

点击“站点”

将 htt://localhost 和 http://10.122.89.28/ 本机IP 添加进去
下面的复选框的勾去掉才能添加
如果大家还有其它CAB打包注册ActiveX的方法 欢迎能交流 共同学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具