在 .NET 中一步步创建 ActiveX






4.74/5 (59投票s)
本文将详细介绍如何在 .NET 中创建 ActiveX,以及如何在 HTML 页面上使用它。
引言
在我之前的工作中,我有一个项目,需要交付一个关于创建、分发和运行 ActiveX
控件(用 .NET 编写)的解决方案。本文总结了所有这些内容。文章中的所有内容都可以在网上找到,但请相信我,这并不容易;)。
Using the Code
- ActiveXSourceCode.zip - 包含 ActiveX 的 .NET 源代码
- Setup.zip - 包含创建 CAB 所需的 *.ini 文件示例
- Web.zip - 嵌入
ActiveX
对象的 HTML 文件示例
那么,我们开始吧...
1) 创建 .NET ActiveX
您需要做的第一步是创建 ActiveX
控件 : )。
您可以在此处找到关于此主题的优秀介绍。
本文介绍了如何在网站上创建和公开 Windows 窗体。由于 .NET Framework 中没有此类支持,WinForms 被封装到 ActiveX
中,这正是我们需要的。总之,我们需要创建一个类,并为其添加这些属性:
[ProgId("MyClassName")]
[Guid("MyGUID")] sdf
[ComVisible(true)]
其中
ProgId
是将被公开为COM
对象的类的唯一名称。ClassInterface
是包装我们 .NET 类的COM
接口的类型。Guid
是允许我们的类用作COM
对象的唯一GUID
。要创建新的GUID
,您可以使用 Visual Studio 中的工具“工具 -> 创建GUID
”。ComVisible
表示我们的类可以用作COM
对象。
注册 COM
对象意味着您需要在注册表中进行一些条目。您可以手动进行,也可以在 ActiveX
中编写方法,当您使用 regasm 等工具注册它时,这些方法会为您完成注册。
///<summary>
///Register the class as a control and set its CodeBase entry
///</summary>
///<param name="key">The registry key of the control</param>
[ComRegisterFunction()]
public static void RegisterClass ( string key )
{
.
.
.
}
///<summary>
///Called to unregister the control
///</summary>
///<param name="key">The registry key</param>
[ComUnregisterFunction()]
public static void UnregisterClass ( string key)
{
.
.
.
}
在实现这些方法后,您现在可以使用命令:regasm /codebase MyAssemblie.dll
来运行 RegisterClass
方法,以及使用 regasm /u MyAssemblie.dll
来运行 UnregisterClass
方法。
为了将您类中的 .NET 方法和属性公开为 COM
方法和属性,您必须在它们前面添加标记 [ComVisible(true)]
,例如:
[ComVisible(true)]
public void Open()
{
.
System.Windows.Forms.MessageBox.Show(MyParam);
.
}
[ComVisible(true)]
public string MyParam
{
get
{
return myParam;
}
set
{
myParam = value;
}
}
您必须记住,您的程序集必须使用强名称密钥进行签名,这样您才能使用更复杂的控件、程序集和功能(例如将事件传回浏览器)。要创建新的 SNK,您可以使用工具:sn.exe(可以在 .NET SDK 中找到)。
sn –k Kosmala.Michal.ActiveXReport.snk
创建强名称密钥后,将其复制到您的项目路径,并在 AssemblyInfo.cs 文件中将其路径放在
[assembly:AssemblyKeyFile("../../Kosmala.Michal.ActiveXReport.snk")]
注册了 COM
对象类后,您现在可以在 Web 页面上使用它了。
2) 在 HTML 页面上使用 ActiveX
要在 HTML 文件中开始使用您的 ActiveX
,只需添加一个标签即可。
<OBJECT id="OurActiveX" name=”OurActiveX" classid="clsid:MyGuid"
VIEWASTEXT codebase="OurActiveX.cab">
其中
id
和name
是从 JavaScript 访问我们ActiveX
时使用的值。classid
是我们ActiveX
的GUID
,我们在 C# 代码的[Guid("MyGUID")]
部分中将其放入。Codebase
是当系统上找不到具有我们GUID
的ActiveX
时应该启动的文件路径。这是放置安装程序(封装在 CAB 中)的地方。
现在,我们暂时忽略 codebase
部分,因为我们正在计算机上进行所有操作,并且可以使用 regasm
注册 ActiveX
。
现在我们的 Web 页面知道了我们要使用哪种 ActiveX
,我们就可以开始实际使用它了。
为此,我们只需在页面上编写一些 JavaScript 代码。这段代码可能看起来像这样:
<script language="javascript">
//Passing parameters to ActiveX object
function OpenActiveX()
{
try
{
document.OurActiveX.MyParam = "Hi I am here."
document.OurActiveX.Open();
}
catch(Err)
{
alert(Err.description);
}
OpenActiveX();
}
</script>
此脚本将为 MyParam
赋值,并调用我们 C# 代码中的 Open()
方法,该方法将返回一个显示“I am here
”文本的消息框。 Open
只是一个方法名,您可以任意命名。
变量赋值是双向的。您也可以使用 JavaScript 从 ActiveX
字段读取值。
请记住,在 Internet Explorer 中设置正确的安全值,以允许运行 ActiveX
。
3) 创建 .cab 组件
现在是时候创建 CAB 文件了,当浏览器在系统中找不到我们注册的 ActiveX
时,将启动该 CAB 文件。首先,您需要创建一个安装程序,该安装程序可以是 MSI,也可以是将 MSI 封装到 setup.exe 文件中。我通过使用 InstallShield 应用程序完成了此操作,因为这是我公司的标准,但您可以使用 Visual Studio 来完成(尽管我从未测试过)。重要的是,您的安装程序必须在目标计算机上注册您的 ActiveX
。这可能需要管理员权限。
有了安装程序后,您就必须创建 CAB。为此,您可以使用 cabsdk
,您可以在此处找到它。
现在,关于我们的 CAB 的重要之处在于,它不仅要附加我们的安装文件,还要附加描述 CAB 内容和应启动哪个文件的*.ini 文件。我们的 OurActiveX.ini 可能看起来像这样:
[version]
signature="$CHICAGO $"
AdvancedINF=2.0
[Add.Code]
setup.exe=setup.exe
[setup.exe]
file-win32-x86=thiscab
clsid={MyGuid}
其中
[Add Code]
部分描述了文件的哪些部分映射到哪个文件。在本例中,只有一个 setup.exe 文件,它由同名的部分映射。[setup.exe]
部分是前一节中定义的部分。它说明了映射到的文件将在通过正确的clsid
访问时启动。在本例中,这就是我们在 C# 代码以及<OBJECT>
标签中定义的MyGuid
。
现在我们拥有了所有需要的文件,我们可以使用 cabsdk
通过以下命令创建 CAB 文件:
cabarc.exe n OurActiveX.cab OurActiveX.inf setup.exe
Voilà。我们的基本 ActiveX
及其分发属性已准备就绪。
现在,来点更复杂的 : )。
4) 从 ActiveX 调用 JavaScript 方法
有时可能需要从 ActiveX
发送一个 JavaScript 可以捕获的事件,例如,当您希望在关闭 ActiveX
时重定向网页。
为此,您需要更新 C# 代码。您需要添加一个新的 interface
和一个新的 delegate
:
public delegate void ControlEventHandler(string redirectUrl);
/// <summary>
/// This interface shows events to javascript
/// </summary>
[Guid(NewGuid)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ControlEvents
{
//Add a DispIdAttribute to any members in the source interface
//to specify the COM DispId.
[DispId(0x60020000)]
void OnClose(string redirectUrl);
}
此代码创建了一个 interface
包装器,它将作为 COM
对象在外部可见。任何可供 COM
使用的新事件都必须标记 DispId
属性。
(创建 .NET 到 COM 对象 http://www.csharphelp.com/archives/archive281.html)
现在,我们需要继承我们的新接口到 ActiveX
控件中:
[ClassInterface(ClassInterfaceType.AutoDual),
ComSourceInterfaces(typeof(ControlEvents))]
由于我们实现了 ControlEvents interface
,现在我们必须在类中创建 OnClose
事件,我们可以在 ActiveX
中引发该事件:
public event ControlEventHandler OnClose;
编译此代码后,我们必须使用附加参数“/tlb
”注册我们的 ActiveX
控件(regasm
),这将从我们的 DLL 中提取 tlb COM
库并将其注册到我们的系统中。
regasm /codebase /tlb MyAssemblie.dll
有了这样的代码,我们就可以在 JavaScript 中添加此事件的处理程序了:
<script language="javascript">
function OurActiveX::OnClose(redirectionUrl)
{
window.location = hostUrl + "/" + redirectionUrl;
}
</script>
事件仅在整个页面加载完成后附加,因此为了使用它,我们必须更改调用 JavaScript 函数的方式:OpenActiveX
。现在我们有两种方法可以做到:
-
我们可以将我们的函数附加到(例如)一个按钮,我们的
ActiveX
将在我们单击它时运行:<input type=button onclick=javascript:OpenActiveX()>
-
如果我们希望它在页面加载后自动启动,我们必须将我们的函数附加到 body 事件“
onload
”:<body onload=OpenActivex()>
您必须记住,您的 ActiveX
程序集必须签名并使用附加参数“/tlb
”进行注册。
这是一个非常简单的 ActiveX
,但它可以调用您的用户有权访问的任何 WinForms 控件或应用程序。
关注点
正如您所见,在 .NET 中创建和分发 ActiveX
非常容易,但很难在网上找到正确的答案,可能是因为现在使用 ActiveX
的人不多了。
我希望本文能尽可能地缩短您的搜索时间。
历史
- 2008 年 3 月 4 日:初始发布