Sunday, August 22, 2004

 

Some notes on Winform in IE and native Dll publication

1.
将一个ClassLibrary (dll) 发布为web servic

作者:阿好
出处:http://www.cnblogs.com/hbzxf/archive/2004/06/12/15173.aspx

WEB METHOD中读取配置文件反射生成

在某一WEB METHOD中,被调用返回一个STRING
Assembly a = Assembly.LoadFile(@"E:\JasonBackUp\StorePictureIntoSql\MyDll\bin\Debug\MyDll.dll";
Type t = a.GetType("MyDll.Class1";
string b = "";
b = t.GetField("Number".GetValue(b).ToString();
return b;

hBifTs 指出
呵呵,其实最好不要使用Assembly.LoadFile这个方法...
这样有可能会在程序运行时多次Load同一个文件.最好是用Load方法~

(按:虽然效率不高,但是非常简单,以前写的很多东西可以这么改造,进行处理)

2.
Using Windows Forms Controls in Internet Explorer

From http://samples.gotdotnet.com/quickstart/winforms/doc/WinFormsIeSourcing.aspx

This topic describes how to successfully execute Windows Forms controls within Internet Explorer (IE). Windows Forms controls within IE are activated without a user prompt, require no registration, and utilize the common language runtime (CLR) code access security.

There are five steps in getting a Windows Forms control activated within Internet Explorer, and each is listed here and detailed below.

Create the Windows Forms control.
Create an HTML document with an object tag.
Create the virtual directory and set permissions.
Run the control.
Create the Windows Forms Control
Almost any Windows Forms control can be hosted in Internet Explorer, but for this example we will host the SimpleControl that is included in the Creating Controls section of this QuickStart tutorial. The control must be installed to the global assembly cache or be present in the same virtual directory as the web page that contains it.

Create an HTML document with an object Tag
The next step is to create an HTML document with an object tag that refers to the Windows Forms control. For this sample, some simple script and input tags will also be added to demonstrate programmatic access to the control.

object id="simpleControl1"

classid="http:SimpleControl.dll#Microsoft.Samples.WinForms.Cs.SimpleControl.SimpleControl"
height="300" width="300" VIEWASTEXT>

/object>


The classid has two interesting parts: the path to the control library, and the fully qualified name of the control, separated by the pound sign. If you are familiar with an ActiveX object tag, you will notice the lack of a guid. In the case of Windows Forms, the combination of the path and fully qualified class name serve as the unique identifier.

Param tags may be used to set properties on controls. In this case, the name attribute is the name of the property and the value attribute is the value of the property.

script>

function ChangeText() {
simpleControl1.Text = text1.value;
}

/script>


input type="text" id="text1">
input type="button" value="Change Text" onclick="ChangeText()">


To gain programmatic access to your control, you can write script against it. A button and text box on the page is used in conjunction with the simple JScript function ChangeText to set the text property of the control. The following is the complete HTML and script code for this example.

html>

script language="JScript">

function ChangeText() {
simpleControl1.Text = text1.value;
}

/script>

body>

p>Simple Control
br>
br>
/body>

object id="simpleControl1"

classid="http:SimpleControl.dll#Microsoft.Samples.WinForms.Cs.SimpleControl.SimpleControl"
height="300" width="300" VIEWASTEXT>
param name="Text" value="Simple Control">
/object>

br>
br>

input type="text" id="text1">
input type="button" value="Change Text" onclick="ChangeText()">

/html>

Create the Virtual Directory and Set Permissions
The HTML page must reside in an IIS virtual directory on your web server, and have appropriate permissions. In this example, the Windows Forms control resides in the same directory, but it can also be installed in the global assembly cache. Execution permissions on the virtual directory must be set to scripts -- the control will not be properly activated if the execution permissions are set to scripts & executables. For this sample, these steps have been performed for you.

Run the Control
To run the control, just point Internet Explorer to the HTML page in your virtual directory. If the control is not activating correctly, it may be necessary to restart Internet Explorer. To view and run this sample, click the icon below.

3.
.Net 中IE使用WinForm控件的使用心得

By submaie
From http://www.cnblogs.com/submaie/archive/2005/03/31/62819.html

WinForm控件确实是个好东西,它可以让IE在客户端的功能大大的增强,但是许多人用的都不多。原因是什么?安全问题。

.Net Framework提供了比ActiveX控件强大得多的安全模型。这里我不准备多说.Net安全方面的知识,.Net Framework SDK 文档中有详细的解释。在这里还是以一个例子描述。

现在打开Vs.net 2003,新建一个Windows控件库项目,项目名称是Namespace.Client ,然后把自动生成的类名称改为TestForm。在设计视图中从工具箱拽一个Button控件放在控件窗体上。

从解决方案资源管理器中的项目中新建一个Windows窗体,窗体名称随便,这里是PopForm,在这个窗体中添加一个按钮,在按钮的单击事件中添加一句代码:
this.Close(); 然后返回TestForm控件设计界面,在添加的窗体按钮上双击,专项代码视图。在类声明的下方私有成员定义中添加一句:
private PopForm pForm = null; 然后在按钮单击事件定义中写如下代码,假设按钮ID为btnOpen:
private void btnOpen_Click(object sender, System.EventArgs e)
{
if(this.pForm == null)
{
pForm = new PopForm();
pForm.ShowDialog();
}
else
pForm.ShowDialog();
}
上面的代码很简单,就是新建一个WinForm控件,在控件中添加一个按钮,这个按钮打开一个名叫PopForm的窗体,PopForm窗体中有个按钮,负责关闭。
编译以后,生成一个名为:Namespace.Client.dll的.Net程序集。

现在把这个程序集加入到Asp.Net页面中,代码如下:

object classid="http://www.host.com/global/Sanxing.WinControls.dll#Sanxing.WinControls.ClientTest" VIEWASTEXT>
/object>

实际上不用.aspx也可以。不过有一点要注意,不能使用本地的LocalHost作为测试站点,因为本地的LocalHost站点的默认具有编辑/管理权限的就是管理员组的成员,使用它这个控件会正常显示。解决方法是放在远程的Web服务器上测试,如果没有远程服务器,可以在本地计算机上模拟一个,在本地计算机的网卡上多添加几个Ip地址,如 192.168.0.2 ,192.168.0.3,然后通过本地计算机上的DNS服务把192.168.0.2绑定上一个私有域名,如 www.host.com 然后在IIS中新建一个Web站点,把192.168.0.2绑定到这个站点上,然后就可以通过www.host.com来访问本机上的站点了。

现在执行这个页面,可以肯定,这个控件的所有界面显示不出来。可能会出现什么都显示不出来,也可能出现一个方框里面一个红色的叉。.Net运行时可能弹出一个对话框,表示这个控件没有任何权限,实际上,出现这个结果是微软的默认设置造成的,作者必须在控件所在的控件的 AssemblyInfo.cs/vb 中执行一个安全声明,声明这个控件必须使用赋予的权限,才可以显示出界面。

我们看一下.Net的安全配置中为Internet区定义的权限。这个区定义了在Internet的网页中下载/执行的程序集可以做的事情。
打开“控制面板” --> “管理工具” --> “Microsoft .Net Framework 1.1 配置” --> “运行库安全策略” --> “计算机” --> “代码组” --> “All_Code” --> “Internet_Zone”,单击“编辑代码组属性”,切换到“权限集”标签后,下面的列表框里面显示的就是从Internet区域下载的程序集可以拥有的权限。 (按:似乎应该是是.net wizard里面,adjust .net security,选择受信任站点,设置为full trust即可。 然后在你的IE里面,把这个受信任站点加进去。格式形如: file://someRemoteServer 或者: http://someUrl )

可以看出,从Internet上执行的程序集可以有界面,可以弹出对话框,还可以打印,但是为什么刚才我们写的WinForm控件在IE中什么也显示不出来呢?

原因是我们没有在控件中声明需要的权限。当在代码中没有声明权限时,.Net的运行时安全管理将不知道我们要使用什么权限,那么安全管理将默认的“无权限”赋予这个控件,那么这个控件连显示介面的权限都没有,当然无法显示了。
所以可以用一个特殊的安全特性声明在控件中,这个声明表示这个控件要求使用客户端的控件权限,而且保证不超过.Net默认的权限,那么.Net通过这个特性了解控件需要默认权限后,会赋予控件权限。这样控件就显示出来了。

这个声明语句就是在AssemblyInfo.cs中添加一句:
[assembly : AllowPartiallyTrustedCallers()]
上面的代码就是声明的含义就是:此程序集需要.Net安全设定中定义的默认权限,且不会超过这个默认权限。

客户端.Net运行库在执行这个控件的代码时,会检测到这个声明,就会把Internet_Zone区的权限赋予这个控件。这样,空间就显示出来了。

但是,这种办法有缺陷,就是只能使用.Net默认设置的权限。客户端无法访问文件,无法访问注册表,连数据库都无法访问。除了显示窗口外什么都不能干。而且显示的窗口有这样的警告。


表示这个窗口所能执行的代码是受到限制的。

这个办法实际上很好,因为WinForm控件主要的目的就是在客户端显示窗口,最重要的就是访问打印机。如果没有什么特殊的用途,则这个方法可以在互联网的公用网站上使用,可以给大家用,只要大家的客户端安装了.Net运行库。

但是如果要在客户端执行高级操作,需要更多的权限,如访问注册表,访问数据库,执行网络操作等。这个方法就不适用了,因为它已经越过了.Net的默认设置,必须用其他的办法来越过.Net的默认安全设置。

(按:建议双机调试,否则改来改去太痛苦)

4.
另外一个例子

http://www.microsoft.com/China/Community/program/originalarticles/TechDoc/xmlwebprint.mspx

5.
在IE浏览器中使用Windows窗体控件

作者::Thiru Thangarathinam
翻译:秋枫
From http://blog.csdn.net/zhzuo/archive/2004/05/10/22032.aspx
http://blog.csdn.net/zhzuo/archive/2004/05/10/22033.aspx
http://blog.csdn.net/zhzuo/archive/2004/05/10/22034.aspx

引言

在过去,Web程序员经常在他们的Web程序中使用ActiveX控件来实现一些胖客户端才具有的功能。不过现在开发者可以很容易的通过Microsoft.NET Framework来简洁和安全的建立对象,并且方便的在IE浏览器中切入使用。通过在IE浏览器中创建Windows窗体控件,开发者可以实现丰富的web客户端。在这篇文章中,我们将会知道怎样创建Windows窗体控件并且在IE中使用。在浏览器中使用窗体控件过程中,我们会演示怎样通过窗体控件来提供丰富的web客户端显示,而窗体控件用来调用远程Web service获取数据。与此同时,我们也会知道怎样利用.NET安全模型来为我们的窗体控件提供一个安全的运行环境。

如果你有过用Java开发Web程序的经验,那你会很熟悉Java applets。它是一个运行在浏览器中的一个小程序。当浏览器打开包含有Applet 标签的HTML文档时,Java applets就会运行。Windows窗体在web页里的工作方式同Java applets很相似。在这个实现中,你创建窗体控件,并为他加上丰富的Windows窗体控件样式,接着切入到Web页面中。在浏览器加载该Web页面的时候,Windows控件所包含的代码也会被执行。在局域网或者扩展的网络程序中这个将会是很有用的。比如想开发一个企业使用的具有胖客户端特性的基与web的程序。

.NET的一个重要特征就是跟IE紧密结合。比如,我们可以在IE中使用Windows窗体控件,而不需要通知用户需要加另外的东西。这个不需要注册什么.NET CLR就会提供代码安全访问的能力。

当你创建Windows窗体控件,你会有窗体类层次提供的特征。比如,你可以使用Windows窗体控件验证技术来验证输入数据的准确性。同样的,你甚至可以在你的窗体控件中调用Web Service。通过这些技术使用,你可以创建基与.NET平台的丰富的、健壮的、动态应用程序。

备注:按照原文重写了代码,把载图替换成了中文,运行环境:操作系统windows2003,.NET Framework 1.1.这里讲几点:调试过程中打开浏览器输入完整地址。如果以文件方式打开将不会显示窗体控件;另外对于进程的调试,可以是单个源文件。不过我运行的是Debug版本下生成的组件,不是Release的,有兴趣读者可以试试。

执行

在这节,我们就会明白怎样创建Windows窗体控件并在IE中使用。下面列出了五个步骤来完成这一过程。

1.创建Windows窗体控件

2.创建一个带有object 标签的HTML文档,该标签用来标识Windows控件

3.配置控件的虚拟路径

4.设置代码访问权限

5.运行控件

接下来让我们来看看上面的各个步骤。

1.创建一个windows窗体控件

在这一步中,我们创建一个简单的Windows窗体控件。控件实现的功能是显示”Hello World”给用户。我们先来建立一个Windows 控件库项目取名为HelloWorldControl,修改默认的用户控件为HelloWorldCtl。接着在控件中加入一个Label,取名为lblDisplayMessage,同时增加了一个按钮btnClick。当用户点击按钮时,将会执行下面的代码用来显示消息给用户。

private void btnClick_Click(object sender, System.EventArgs e)

{

this.lblDisplayMessage.Text = "Hello World";

}

接着就是编译他生成一个Assembly。


2.创建HTML页

在这一步中,我们将创建一个HTML文档并在里面插入object标签。整个文档看起来如下:

html>
body>
p>Hello World Control
OBJECT id="HelloWorldControl1" height="300" width="300" classid="http:HelloWorldControl.dll#HelloWorldControl.HelloWorldCtl"
VIEWASTEXT>
/OBJECT>
br>
/p>
/body>
/html>

在这个标签的classid 属性中,我们指定第一步创建的那个组件的路径以及组件完整限定名。整个完整名称包括命名空间和整个类名。我们可以在上面的代码中清楚的看到组件名和限定名用#分割。这两部分参数组合在一起用来标识控件的唯一性。当然可以通过取名唯一id为HelloWorldControl1来编写客户端脚本。

3.配置虚拟路径

有了HTML页面,现在来建立一个HelloWorldControlHost的虚拟目录,实际目录在D:\My Programs\HellpWorldHost,该目录包含了HelloWorldControl.dll和Hellpworld.htm文件。当设置虚拟目录的时候,需要注意的是设置执行权限为“纯脚本”。如果设置成“脚本和可执行脚本”的权限。那控件可能不会正常工作(我在IIS6下设置成“脚本和可执行脚本”,不正常)。你可以打开虚拟目录的属性来确认设置。dll和html页面一定要在同一个文件夹下的。


4.设置代码访问权限

如果这个web在局域网中访问,他会正常工作。如果该Web是通过Internet来访问,那你需要设置internet Explorer,修改安全属性以允许他运行。你可以把主页加入到受信任的站点。如果需要设置可以通过IE的工具菜单―>Internet选项->安全->受信任的站点,点击上面的站点按钮把你的网站加入其中。接下去,当你打开浏览器查看,就会看到正确执行。

5.运行控件

要运行这个控件,我们在浏览器中查看包含了控件的那个Html页面。假如你在页面上点击这个按钮,那么控件就会显示“Hellp World”信息,执行页面如下:

通过windows窗体控件访问Web Service


窗体控件一个重要优点就是你可以通过它在客户端实现丰富的用户信息。比如说,你可以通过窗体控件对Web服务的访问从而在IE中显示而不需要重新刷新该页面。为了演示这点,我们先来创建一个Web服务,接着再来演示怎样通过窗体控件调用Web服务。

创建Web service

我们创建一个 Visual C# Asp.net web service 新项目,名字取为AuthorsWebService。

建立以后,我们修改服务类名称为AuthorsService,同时在类里面增加一个GetAuthors方法到里面,该方法的代码如下:

[WebMethod]

public DataSet GetAuthors()

{

string connString = System.Configuration.ConfigurationSettings.AppSettings["connectionString"];

SqlConnection sqlConn = new SqlConnection(connString);

DataSet dstAuthors = new DataSet("Authors");

SqlDataAdapter adapter = new SqlDataAdapter("Select * from Authors",sqlConn);

adapter.Fill(dstAuthors,"Author");

sqlConn.Close();

sqlConn.Dispose();

return dstAuthors;

}

上面方法的代码比较简单,我们把数据库连接字符串储存到了Web.config文件的appSettings节点上,如下:

appSettings>

add key="connectionString" value="server=localhost;uid=sa;pwd=thiru;database=Pubs">

/appSettings>



上面代码中,
我们创建了一个SqlConnnection实例,同时把上面的连接字符串作为参数传入。接着创建一个SqlDataAdapter对象,传入两个参数――查询字符串和SqlConnnection实例。调用SqlDataAdapter实例的Fill方法来执行数据库查询并把结果填充到DataSet。现在我们完成了Web服务的创建,接下去来建立一个他的一个客户端调用。

创建windows窗体控件作为Web服务客户端

在这里,我们是想用一个窗体控件来调用Web Service,因此新建一个Visual C#窗体控件项目取名AuthorsWebServiceClientControl:。

完成后,修改默认用户控件名称为AuthorsControl.。我们在上面添加了一个DataGrid控件取名GridAuthors 同时添加一个按钮取名BtnClick。注册按钮的点击事件,在事件处理函数中,将会调用WebService。在这之前我们需要添加项目的Web引用,输入刚才创建的Web服务地址。编辑器会生成该服务的代理。

服务代理创建以后,我们在按钮事件中添加代码:

private void BtnClick_Click(object sender, System.EventArgs e)

{

this.Cursor = Cursors.WaitCursor;

AuthorsWebServiceProxy.AuthorsService authorsSvc = new

AuthorsWebServiceProxy.AuthorsService();

this.GridAuthors.DataSource = authorsSvc.GetAuthors();

this.Cursor = Cursors.Default;

}

在上面代码中,我们创建了web服务代理的一个实例,并调用GetAuthors方法把返回的数据集赋值给GridAuthors的DataSource属性。接着编译这个窗体控件,然后配置虚拟目录。

创建Html页面和建立虚拟路径

在这一步中,我们通过创建一个Html页面来使用上面创建的那个AuthorsWebServiceClientControl。下面是他的代码:

html>
body>
p>Authors Display Control
object id="AuthorsControl1"
classid="http:AuthorsWebServiceClientControl.dll#AuthorsWebServiceClientControl.AuthorsControl"
height="500" width="500" VIEWASTEXT>
/object>
/body>
/html>

现在我们需要创建一个虚拟目录使该控件能正常工作,并把AuthorsDisplay.htm和AuthorsWebServiceClientControl.dll放在一起。打开该浏览器输入地址,你就会看到一个按钮和一个空的DataGrid,如果你点击该命令按钮,控件就会调用Web服务同时把结果写到了DataGrid中。页面结果如下所示。

调试Windows窗体控件

要调试窗体控件,你需要按照下面步骤进行。

1.打开浏览器并请求包含窗体控件的那个Html页面。

2.打开visual Studio.Net同时选择工具->调试进程就会显示下面的对话框。

在这个进程对话框中,选择IEXPLORE.EXE 点击附加按钮。当你点击附加按钮时会跳出一个对话框提示你选择要调试的程序类型。我们选择了Common Language Runtime 和Script两项。确定关闭上面的窗口和进程窗口。

通过Vs.net的文件菜单打开用户控件文件 AuthorsWebServiceClient.cs,在源代码中设置断点。这样一旦你设置断点,你就可以调试该控件了。

Windows窗体代码访问权限

就象我们以前讨论的一样。当窗体控件在IE中执行时,他使用由.NET运行时提供的权限。要弄清楚控件怎样使用由.NET运行时提供的代码访问安全来在IE中运行,让我们回到前面,在窗体控件Load事件中加入下面的代码:

private void AuthorsControl_Load(object sender, System.EventArgs e)

{

if (!EventLog.SourceExists("TestSource"))

EventLog.CreateEventSource("TestSource", "TestLog");

else

{

EventLog.DeleteEventSource("TestSource");

EventLog.CreateEventSource("TestSource", "TestLog");

}

}

在上面的代码中我们判断web服务器上是否存在”TestLog”的日志源,如果不存在我们就创建他,如果存在就删除重建。就象你预料的一样,执行这些代码需要有更多的权限,所以上面的代码通过Internet该用户控件将不会正常工作,你将会看到如下的提示窗口。

通过上面窗口我们可以清楚的看到你的访问被.NET运行时所限制。

在IE中使用窗体控件时,你需要意识到他的优点和局限。主要的优点包括:

1.通过Web实现丰富的动态界面。

2.无缝结合.NET的代码安全策略。

3.优于Java applets的表现。

限制包括:

1.客户端需要是Windows操作系统

2.需要IE6.0的支持

3.客户端需要安装.NET运行时环境

4.服务器端需要是Window2000和IIS5.0或者更高版本

由于上面的限制,对客户端和服务器端数据的传输这也许也是有利的。比如说由于让Windows窗体控件在客户端IE中使用需要客户端安装有.NET runtime,我们可以写一些代码来判断客户机是否安装有.NET runtime,通过这一特征我们可以获得版本号,否则会得到0.0。

结论

在这篇文章中,我们讨论了怎样在IE中使用浏览窗体控件以及在进程中进行调试。同时也讲到了在IE中的.NET代码访问安全控制。

虽然这项技术的实现需要客户端安装.NET运行时,不过我们可以相信在以后的Windows操作系统中将会集成.NET framework,windows2003就是一个很好的例子。

最后,我希望你会发现这篇文章对你有所帮助,同时谢谢你的阅读。

6.
WinForm与脚本的交互

By sniper
From http://www.cnblogs.com/sniper/archive/2004/08/09/31339.html

将Winform Control嵌入IE,很多时候需要JS脚本与Control进行交互。一方面是在脚本中使用控件的属性,调用控件的方法,另外一方面是脚本中能够响应控件的事件。对于第一个问题较为简单,我们还可以在脚本中使用控件属性的值,也可以给属性赋值,也可以调用控件的方法。

1、 脚本中传参数,使用控件的属性,调用控件方法

1)在控件Test_JsUseCtrl.cs中,添加textBox1,定义属性Str,如

private string str;

public string Str

{

get{return str;}

set{ str = value;textBox1.Text = value;}

}

2)定义public方法用于显示textBox1内容如

public void ShowText()

{

MessageBox.Show(textBox1.Text,"TextBox的内容", MessageBoxButtons.OK,MessageBoxIcon.Information);

}

3)在页面添加TextBox,Button等,点击Button1可以将页面输入值赋给控件属性,点击Button2可以调用控件方法

function Button1_onclick() {

Test_JsUseCtrl.Str = Text1.value;

}

function Button2_onclick() {

Test_JsUseCtrl.ShowText();

}

上面部是点击或者触发页面控件事件来获得控件的属性和方法,下面部分就是控件通过事件来调用脚本中的方法,即在脚本中响应控件事件。

2、JS脚本中响应控件事件


1)在控件中添加接口ClickEvent

// Source interface for events to be exposed

// Add GuidAttribute to the source interface to supply an explicit System.Guid.

// Add InterfaceTypeAttribute to indicate that interface is the IDispatch interface.

[System.Runtime.InteropServices.GuidAttribute("0422D916-C11A-474e-947D-45A107038D12") ]

[System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)]

public interface ControlEvents

// Add a DisIdAttribute to any members in the source interface to // specify the COM DispId.

{

[System.Runtime.InteropServices.DispIdAttribute(0x60020000)]

void ClickEvent(int x, int y);

}



2、为控件添加属性

// Add a ComSourceInterfaces attribute to the control to identify //the list of interfaces that are exposed as COM event sources.

[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None),System.Runtime.InteropServices.ComSourceInterfaces(typeof(ControlEvents))]

public class MyWindowControl : System.Windows.Forms.UserControl //, ComInteropControlInterface

2、 在Button的Click事件中调用接口方法

if (ClickEvent != null)

{

ClickEvent(0, 0);

}

3、 在JS脚本中响应接口事件

function ctrl::ClickEvent(a,b)

{

alert(String(a)+"+"+String(b));

}

脚本响应控件的事件稍微复杂

注:如果弹出关于安全方面的提示,把IE->安全->信任站点s->自定义级别下的,“对没有标记为安全的ActiveX控件进行初始化和脚本运行”,设为启用。(上面的思路就是将Control作为ActiveX)

参考:
HOW TO: Sink Managed C# Events in Internet Explorer Script
http://support.microsoft.com/?kbid=313891

PRB: Security Exception When You Use Event Handlers in Internet Explorer
http://support.microsoft.com/default.aspx?scid=kb;EN-US;316510

7.
用C#编写ActiveX控件

By Jirong's Groovey
From http://www.cnblogs.com/jrzhou/archive/2005/01/05/86992.html

上回跟bloodchen有过类似的讨论,用.net编写Maxthon的Sidebar Plugin。

这个应该不能算是真正的ActiveX,可以到Add Reference试试,你没有办法将它添加到你的winform project里,IE是市面上唯一官方提供support的unmanaged host for winform control,smart application一部分,如果您在.net安全向导里设置允许直接运行.net程序,点击.exe的链接,IE会自动调用framework来运行这个managed component。可以参考wahoo这个winning application. http://www.sellsbrothers.com/wahoo/

MS在.net framework 1.0 beta里有文档说明如何将Winform Usercontrol publish为activex,但是1.0 release不再支持。如果有兴趣可以参考Chris Sells和Morgan Skinner的文章。http://www.ondotnet.com/pub/a/dotnet/2003/01/20/winformshosting.html
http://www.codeproject.com/cs/miscctrl/exposingdotnetcontrols.asp

8.
用C#编写伪ActiveX控件

By 红马天下
From http://www.cnblogs.com/homer/archive/2005/01/06/87423.html

前些日子做一个Web项目,必须自己编写一个ActiveX控件。如今的ActiveX控件大多是使用VB/C++来开发的,而我对他们并不熟悉,因此考虑使用熟悉的C#编写ActiveX控件。

首先,建立一个WinForm控件项目HelloWorld,并拖入一个Label控件,文字设为HelloWorld
此时编译项目,可以生成HelloWorld.dll。将此dll拷贝到IIS的虚拟根目录下,然后建立一个helloworld.htm的文件,html代码如下:

body bgcolor='#223344'>
object id="helloworld" classid=’http://localhost/HelloWorld.dll#HelloWorld.Demo’ Width="184" Height="96" VIEWASTEXT> /object>
/body> 在IE地址栏中输入以下地址:http://localhost/helloworld.htm,出现界面:

如图,控件已经成功在页面上显示了。OK,我们已经完成了第一步。

但是问题到这里还没有解决。不相信?你可以试试在另外一台机器上测试,注意需要修改对应的html代码和URL地址。你可以看到这个在原来显示控件的地方是一个红色的叉,或者还会弹出一个对话框,表示这个控件没有任何权限。出现这个结果是微软的默认设置造成的,作者必须在控件所在的控件的 AssemblyInfo.cs/vb 中执行一个安全声明,声明这个控件必须使用赋予的权限,才可以显示出界面。我们在AssemblyInfo.cs中引用System.Security命名空间,并添加一句:
[assembly : AllowPartiallyTrustedCallers()] 现在重新编译,并且替换以前的dll,界面又可以显示出来了。

需要提醒的是,到现在为止,我们编写的还不是真正的ActiveX控件。这个控件到现在为止,还只是能够实现自身的显示,并且不能实现更多的功能,比如实现与脚本的交互或者操作客户端的注册表或者磁盘。这是由于.Net Framework的安全模型所限制的。如果我们希望这个控件突破.Net Framework安全模型的限制,实现与脚本的交互或者操作客户端的注册表或者磁盘的话,必须要让它成为真正的ActiveX控件。下面,我们把刚才的控件变成真正的ActiveX控件。

首先使用 工具—〉创建GUID 生成一个GUID,并修改UserControl1.cs文件。首先增加引用System.Runtime.InteropServices命名空间,并在Demo前面加入一条语句。注意Guid中的字符串,就是你生成的Guid字符串。它是你所生成的ActiveX控件的唯一标识符。然后修改项目属性,如图:

注意面板中的最后一项,我们唯一需要修改的是将其值改为True。

重新编译。我们使用 工具—〉OLE/COM对象查看器 查看,可以看到,我们写的HelloWorld.Demo已经被正确识别为COM组件。现在,我们已经可以像使用其它ActiveX控件一样在网页中显示了。在HelloWorld.Demo点击鼠标右键,选择Copy HTML object> Tag to Clipboard,可以将代码拷入剪贴板。

现在,我们改写helloworld.htm,html代码如下:

body bgcolor='#223344'>
object id="helloworld"
classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96">
/object>
/body>

使用IE查看,我们的控件又可以在网页中显示了。当然,我们编写的任务还没有完成。首先,我们先尝试实现和JS的交互能力。

我们在Demo中加入ShowMessage方法:

public void ShowMessage(string msg)
{
if(msg != null)
{
MessageBox.Show(msg);
}
}

我们重新编译。在重新访问页面之前,我们先来修改html代码:

body bgcolor='#223344'>
object id="helloworld"
classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96"
/object>
br>
input type='button' onclick='helloworld.ShowMessage(“Hello World!”)' value='Click'>
/body>

现在,重新访问http://localhost/helloworld.htm,单击Click按钮,应该可以实现交互了。

但是结果却很遗憾,我们发现IE跳出了对话框,如图所示:

单击确定之后,我们发现JS报错。根据提示,我们判断可以通过修改IE的设置使控件运行。打开IE的 工具——〉Internet选项——〉安全——〉本地Intranet——〉自定义级别——〉对没有标记为安全的ActiveX控件进行初始化和运行,将其值设为启用。我们刷新页面,现在终于可以正确运行了。

当然,我们不能指望我们的客户和我们一样修改这个值。毕竟,一是操作麻烦,二是给电脑带来了很大的安全风险。在互联网上搜索之后,发现必须要实现IObjectSafety接口,把ActiveX控件标记为安全的ActiveX控件。在搜索MSDN之后,我找到了IObjectSafety接口的定义。这就好办了。首先我们自己用C#实现这个接口:

[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}

注意,这个GUID是不能改的。然后,我们在Demo类里面实现这个接口。增加一下代码:

IObjectSafety 成员#region IObjectSafety 成员

public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
{
// TODO: 添加 WebCamControl.GetInterfacceSafyOptions 实现
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}

public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
{
// TODO: 添加 WebCamControl.SetInterfaceSafetyOptions 实现
}

#endregion

重新编译,然后将IE里面的设置改回来。现在,我们发现,和JS的交互已经没有问题了。

这样,一个最基本的ActiveX控件已经写好了。你可以在这个控件的基础上增加任何你需要的功能。到这里,编写控件的任务已经完成了,我们的下一个目标就是发布它。

首先,我们建立一个windows安装项目,并将ActiveX控件的主输出添加到项目输出中。然后,改动ActiveX控件的主输出文件,将其Register属性改为vsdrpCOM。

下一步,我们改动项目属性,将引导程序更改为 Web引导程序。很遗憾的是,在 Web引导程序设置 中的安装文件夹URL中必须使用绝对路径,不能使用相对路径。这意味着生成安装程序的时候就必须确定路径,不是很方便。在示例中,我使用了localhost,在发布中可以改为实际的域名。

现在我们生成安装程序,并把相应得程序拷贝到正确的目录中(本例中为默认网站目录下的ActiveX文件夹中)。我们可以直接执行Setup.Exe文件,以验证安装文件的正确性。在我的机器上正确执行了,成功了!

现在我们又要重新改动helloworld.htm文件了。修改后的结果如下:

body bgcolor='#223344'>
object id="helloworld"

classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96" codebase="ActiveX/Setup.Exe"
>
/object>
br>
input type='button' onclick='helloworld.ShowMessage("Hello World!")' value='Click'>
/body>

注意,我们在object块中加入了codebase属性,这就是制定的下载控件的位置,可以使用相对路径。别忙,我们现在还不能正确请求这个页面,因为我们还没有对我们的控件进行签名。签名可以采用两种方式,一种是在上面生成安装程序的时候签名,另一种是使用sn.exe签名。推荐大家使用后者,因为可以提供更多选项。本人很懒,就不多写了,大家可以参考csdn上的文章《发布ActiveX》。先给给大家提个醒,在申请证书的时候选择 高级证书申请。

(按:# re: 关于《用C#编写ActiveX控件》的几点说明
>>> 其实用C#写ActiveX控件的原理很简单,就是使用了.net平台和COM的互操作性。

在CodeProject上也有一些类似的文章教如何把Winform UserControl改成ActiveX 控件。
这样做有一定的技术风险的,因为Winform UserControl没有实现和ActiveX控件的完全兼容性。
Winform Dev Team的回答是说一开始是想做成全兼容的,
但是后来遇到很多问题就把这个特性去掉了,所以现在的Winform控件
只有部分的ActiveX控件兼容性

对于你的应用而言你,你其实只需要IE Host winform user control就足够了。
至于访问本地文件等等问题,这和配置code access security就可以了,即使你按照ActiveX的方式创建仍然无法躲过CAS的检查的。

Ying-Shen 评论于 2005-01-07 04:37

# re: 关于《用C#编写ActiveX控件》的几点说明
当然会是使用Delphi或者VC来开发ActiveX了!
既然是B/S程序,那么B/S程序最在的优势是什么?使用C#做的,客户端必须安装相应的Framework才可以。如果客户端都安装了Framework了,那B/S就丧失了他的最大优势。

小李菜刀 评论于 2005-01-08 23:23)



<< Home

This page is powered by Blogger. Isn't yours?