嵌入IE中的Windows用户控件与IE之间的双向通信






4.33/5 (4投票s)
在Internet Explorer网页中嵌入C#用户控件,以及页面与用户控件之间的通信。
引言
我最初的任务是为现有的原生 C++ 代码创建一个 .NET 包装器类,并将其作为 Active X 暴露给网页,但使用 .NET,并设置一个环境,使网页能够与原生代码双向通信。这项任务尚未完成,但我已经找到了客户端网页和 .NET 用户控件之间互通信的解决方案。在本文中,我将展示如何在 Internet Explorer 网页(客户端)上放置 C# 用户控件,以及用户控件如何与网页通信以及从网页返回。通过这种方式,可以构建富客户端 .NET 应用程序。
背景
在 Internet Explorer 中,我们可以使用 <object>
标签嵌入用户控件。用户控件将能够触发一个事件,该事件可以被网页上的 JavaScript 捕获,而 JavaScript 可以调用用户控件的代码。用户控件需要使用 caspol.exe 授予权限。我将为整个站点授予权限(在某些情况下可能存在安全漏洞),而不是为用户控件授予完全信任,因为从 .NET 2.0 开始,如果没有平台 SDK,就不会有 .NET 管理员和全局程序集缓存,除非用户想要下载平台 SDK,只需要框架。
Using the Code
我安装了 Visual Studio 2008 和 .NET Framework 3.5,但没有安装平台 SDK,因此我没有将 gacutil.exe 添加到缓存我的程序集中。
启动安装了 C# 的 Visual Studio 2008,然后按 文件 -> 新建项目。在左侧,单击 C#。现在在右侧,选择 WindowsFormsControlLibrary
。我将我的 WindowsFormsControlLibrary1
重命名为 UserControl3
(以便与我的其他工作区分开),这将默认命名空间从 WindowsFormsControlLibrary1
更改为 UserControl3
- 仅此而已。现在网络上有一些接近工作的示例,这个 和 一个高级示例(您需要从源代码示例中删除 & n b s p 字符),其中有关于事件和委托的说明。还有其他通信示例 在这里。不要忘记为用户控件授予安全权限才能使其工作。这里 有关于此的说明。简而言之,需要将网页添加到受信任站点,为此,启动 Internet Explorer 6 -> 工具 -> Internet 选项,在安全选项卡上单击受信任的站点,然后单击站点按钮,然后在此处添加站点(我已添加我的 LAN IP - http://193.231.162.210)。现在为 Internet Explorer 添加受信任的站点,但我们也需要为 .NET 进行此操作
CasPol.exe -q -m -ag All_Code -zone Intranet FullTrust
CasPol.exe -q -m -ag All_Code -zone Trusted FullTrust
Caspol.exe 默认位于 Windows XP 和 .NET Framework 3.5 的 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 目录下,并且不在 PATH 系统变量中!
现在右键单击 Visual Studio 解决方案资源管理器窗口中的项目,选择属性,单击生成选项卡,然后勾选“注册 COM 互操作”。在解决方案资源管理器窗口中,选择展开项目下的属性节点,然后双击 AssemblyInfo.cs。您应该看到
[assembly: ComVisible(true)]
以及生成的 GUID
[assembly: Guid("936987f7-536b-4a0c-b8f2-37e387d97108")]
进入设计模式,向用户控件添加一个按钮。我已将按钮重命名为 btFireEvent
,并设置了文本:Fire Javascript Event。双击按钮(它将生成正确的处理程序方法)。现在,使用示例和您的源代码在 UserControl1.cs 文件中完成代码。之后,该文件应如下所示
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace UserControl3
{
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface UserControl1Events
{
[DispId(0)]
void SubmitClicked();
}
public delegate void SubmitClickedHandler();
[ComSourceInterfaces(typeof(UserControl1Events))]
public partial class UserControl1 : UserControl
{
public event SubmitClickedHandler SubmitClicked;
protected virtual void OnSubmitClicked()
{
if (SubmitClicked != null)
SubmitClicked();
}
public UserControl1()
{
InitializeComponent();
}
public string WhatTimeIsIt(string msg) {
MessageBox.Show(msg,"Inside C#");
return DateTime.Now.ToString();
}
private void btFireEvent_Click(object sender, EventArgs e)
{
OnSubmitClicked();
}
}
}
构建它!在 bin/Debug 目录下,应该存在所需的 DLL,即 UserControl3.dll。
现在编写 .html 部分
在我的 Web 服务器(Apache 2.0)的文档根目录(htdocs)下,我创建了一个名为 tutorial 的文件夹。将 UserControl3.dll 复制到该文件夹。创建一个新的 .txt 文件。在此文件中输入以下文本<html>
<body>
<object id="SimpleUserControl"
classid="http://193.231.162.210/tutorial/UserControl3.dll#UserControl3.UserControl1"
height="150" width="150" >
</object>
<input type="button" value="What time is it?" önclick="DoWhatTimeIsIt();" />
</body>
<script language="javascript">
function DoWhatTimeIsIt() {
alert(document.SimpleUserControl.WhatTimeIsIt('I am Szabi on Javascript'));
}
</script>
<script for="SimpleUserControl" event="SubmitClicked" language="javascript">
alert("Hello from C# fired event");
</script>
</html>
您应该将 193.231.162.210 更改为您本地 IP 或 localhost 或 127.0.0.1,并将 tutorial 更改为上一步创建的文件夹名称。
关注点
我希望这个示例也能奏效。我希望收到有关如何打包/部署多个托管 .dll 文件(其中一个包含原生 C++ 代码)的帖子。
我尝试过
<link rel="Configuration" href="/path/to/MyControl.config"/>
这已在此 处 进行了说明。
但是使用 .NET 3.5 时,在我的配置文件中找不到 HttpForbiddenHandler
,也无法像这样设置 config 文件
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="blsTree" culture="neutral"
publicKeyToken="007a0b78_bf42c201"/>
<codeBase version="1.0.955.24881"
href="https:///blstree.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>