1、开发及测试环境:
(1)开发环境:
Visual Studio 2008 SP1
cabsdk(下载地址:http://support.microsoft.com/kb/310618)
(2)测试环境:
Windows Server 2003 R2 SP2
IE6
2、创建项目
我这里创建了三个项目:
(1)HelloBossma :
项目模板:Windows窗体控件库
(2)HelloBossmaSetup:
项目模板:安装项目
(3)Web:
项目模板:ASP.NET 网站
3、HelloBossma项目
这个项目用于编写具体的控件,并生成安装文件所需要的dll。
(1)添加用户控件:
(2)设计控件:
添加Panel、GroupBox、Label 控件。NowTime是一个Label控件,用于显示时间。
然后在控件对应的代码文件中编写程序:
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Windows.Forms;
|
using System.Runtime.InteropServices;
|
/// IObjectSafety的是用来标记可安全执行脚本的ActiveX控件
|
[Guid( "636B8CE1-7512-464C-B63C-FC75BDCA21DB" ), ProgId( "HelloBossma.HelloBossmaActiveX" ), ComVisible( true )]
|
public partial class HelloBossmaActiveX : UserControl, IObjectSafety
|
private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}" ;
|
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}" ;
|
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}" ;
|
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}" ;
|
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}" ;
|
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
|
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
|
private const int S_OK = 0;
|
private const int E_FAIL = unchecked (( int )0x80004005);
|
private const int E_NOINTERFACE = unchecked (( int )0x80004002);
|
private bool _fSafeForScripting = true ;
|
private bool _fSafeForInitializing = true ;
|
public HelloBossmaActiveX()
|
/// <param name="timeStr"></param>
|
public void SetTime( string timeStr)
|
this .label2.Text = timeStr;
|
public int GetInterfaceSafetyOptions( ref Guid riid,
|
ref int pdwSupportedOptions,
|
ref int pdwEnabledOptions)
|
string strGUID = riid.ToString( "B" );
|
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
|
if (_fSafeForScripting == true )
|
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
|
case _IID_IPersistStorage:
|
case _IID_IPersistStream:
|
case _IID_IPersistPropertyBag:
|
if (_fSafeForInitializing == true )
|
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
|
public int SetInterfaceSafetyOptions( ref Guid riid,
|
string strGUID = riid.ToString( "B" );
|
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
|
(_fSafeForScripting == true ))
|
case _IID_IPersistStorage:
|
case _IID_IPersistStream:
|
case _IID_IPersistPropertyBag:
|
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
|
(_fSafeForInitializing == true ))
|
关于IObjectSafety的实现参考了:http://www.pinvoke.net/default.aspx/Interfaces/IObjectSafety.html
using System.Collections.Generic;
|
using System.Runtime.InteropServices;
|
[ComImport, GuidAttribute( "CB5BDC81-93C1-11CF-8F20-00805F2CD064" )]
|
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
public interface IObjectSafety
|
int GetInterfaceSafetyOptions( ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
|
int SetInterfaceSafetyOptions( ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
|
这里还包含了一个可以被外部调用的方法,传进来一个字符参数,并显示出来:
/// <param name="timeStr"></param>
|
public void SetTime( string timeStr)
|
this .label2.Text = timeStr;
|
(3)设置生成属性,勾选:为Com互操作注册
(4)生成项目,生成这两个文件:
HelloBossma.dll
HelloBossma.tlb
是必须的,否则生成不成功。
4、HelloBossmaSetup项目
这是一个安装项目,用来生成安装程序。
(1)在项目上点右键,【添加】->【项目输出】,选择上边的HelloBossma项目
(2)在安装项目上点右键,属性
安装URL:貌似用于查找应用程序更新,具体看:http://msdn.microsoft.com/zh-cn/library/c37e68bc(VS.90).aspx
这个目录最好是实际存在的,用来存放生成的安装文件,供客户端下载安装。没有的话就随便输入一个吧。
(3)添加卸载程序
拷贝文件C:/Windows/System32/msiexec.exe文件,修改文件名为Uninstall.exe,添加到安装项目中,然后创建一个快捷方式。
在【用户的“程序”菜单下边】添加一个文件夹HelloBossma,将快捷方式拖动到这里边。
在卸载控件上点击右键,属性:
设置Arguments,就是指定要卸载的程序,后面的ProductCode可以这样获得:
选中项目,然后鼠标放到右侧的“属性”上,就可以看到ProductCode了:
(4)最后生成项目
5、制作CAB文件
(1)为了方便操作,可以将CABARC.EXE添加到环境变量中:桌面上右击“我的电脑”,“属性”,“高级”,“环境变量”,“系统变量”,找到“Path”,在后边把CABARC.EXE所在的路径添加上去,注意用分号隔开新添加的路径。
(2)准备好文件
install.inf :CAB安装配置文件
HelloBossmaSetup.msi:安装程序文件
install.inf文件的内容:
run=msiexec.exe /i "%EXTRACT_DIR%/HelloBossmaSetup.msi" /qn |
run:一般只需要修改这个就行了
(3)执行cabarc命令
桌面左下角“开始”,“运行”,输入cmd,打开命令提示符工具,进入准备好的文件的目录,执行命令:
cabarc n HelloBossma.cab HelloBossmaSetup.msi install.inf
显示“Completed successfully” ,打开所在目录,就可以看到生成的文件了。
6、部署到网站
在网站中新建一个目录hellobossma,将生成的cab文件拷贝到里边。
新建一个网页,将控件添加到页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "< A href = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</ A >">
|
< html xmlns = "<A href=" http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</ A >">
|
< script type = "text/javascript" >
|
var vYear = d.getFullYear();
|
var vMon = d.getMonth() + 1;
|
var vHour = d.getHours();
|
var vMin = d.getMinutes();
|
var vSec = d.getSeconds();
|
document.HelloBossma.SetTime(vYear + "-" + vMon + "-" + vDay + " " + vHour + ":" + vMin + ":" + vSec)
|
< body style = "font-size: 12px; color: black" >
|
< form id = "form1" runat = "server" >
|
< object classid = "clsid:636B8CE1-7512-464C-B63C-FC75BDCA21DB" codebase = "hellobossma/HelloBossma.CAB" width = "442" height = "87" id = "HelloBossma" name = "HelloBossma" >
|
< input type = "button" value = "显示当前时间" onclick = "SetTime()" />
|
ActiveX控件作为一个object添加到页面中,其classid是在编写HelloBossmaActiveX类时定义好的Guid值,codebase用来指示cab安装文件的路径,还可以设置宽度、高度。另外其中文字受页面中字体样式的影响。
因为我们的ActiveX控件没有签名,所以将测试站点加到“本地Intranet”中或者“可信站点”中,并设置安全级别为“低”。
然后打开浏览器,提示安装,点击“安装”,稍等下,效果就出来了:
点击按钮,就可以通过javascript设置ActiveX控件中的时间了。
Over!
分类:
C#2011-05-27 15:52 288人阅读
评论(0)
收藏 举报
上一节介绍了一个ActiveX的例子,后续的文章将针对这个例子进行扩充和说明。这篇文章将介绍C#如何在ActiveX控件中调用javascript的函数,这里参考网上的例子介绍两种方法,虽然代码不一样,但是殊途同归。而且都使用了mshtml。
1、方法一
(1)在VS项目中添加Com对象引用:Microsoft Html Object Library(mshtml.tlb)
(2)ActiveX中公开一个方法,传递window对象到ActiveX中
ActiveX中公开一个方法,接受传递进来的参数
/// <param name="obj">The obj.</param>
|
public void SetHtml( object obj)
|
html = (mshtml.HTMLWindow2Class)obj;
|
在页面中调用ActiveX的公开方法,传递当前window对象进去:
window.onload = function () {
|
document.HelloBossma.SetHtml( this );
|
(3)在ActiveX控件中添加一个按钮,当点击这个按钮时,触发页面中的javascript。
点击按钮的方法:
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void button1_Click( object sender, EventArgs e)
|
html.execScript( "CallByActiveX();" , "javascript" );
|
现在卸载掉原来的ActiveX控件,安装新的控件,打开页面,点击按钮,看到如下效果,说明成功。
调用javascript时还可以传递参数,这里不做演示了,自己可以试一下。
参考:http://www.cnblogs.com/liubiqu/articles/92632.html
2、方法二
(1)在VS项目中添加Com对象引用:Microsoft Html Object Library(mshtml.tlb)
和第一种方法相同。
(2)用c#实现两个COM类,IOleClientSite和IOleContainer
using System.Collections.Generic;
|
using System.Runtime.InteropServices;
|
Guid( "00000118-0000-0000-C000-000000000046" ),
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
public interface IOleClientSite
|
void GetMoniker( uint dwAssign, uint dwWhichMoniker, object ppmk);
|
void GetContainer( out IOleContainer ppContainer);
|
void OnShowWindow( bool fShow);
|
void RequestNewObjectLayout();
|
Guid( "0000011B-0000-0000-C000-000000000046" ),
|
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
public interface IOleContainer
|
void EnumObjects([In, MarshalAs(UnmanagedType.U4)] int grfFlags,
|
[Out, MarshalAs(UnmanagedType.LPArray)] object [] ppenum);
|
void ParseDisplayName([In, MarshalAs(UnmanagedType.Interface)] object pbc,
|
[MarshalAs(UnmanagedType.BStr)] string pszDisplayName,
|
[Out, MarshalAs(UnmanagedType.LPArray)] int [] pchEaten,
|
[Out, MarshalAs(UnmanagedType.LPArray)] object [] ppmkOut);
|
void LockContainer([In, MarshalAs(UnmanagedType.I4)] int fLock);
|
(3)在ActiveX中编写CallJavascript方法:
/// <param name="Filenames">The filenames.</param>
|
private void CallJavaScript( string param)
|
Type typeIOleObject = this .GetType().GetInterface( "IOleObject" , true );
|
object oleClientSite = typeIOleObject.InvokeMember( "GetClientSite" ,
|
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
|
IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite;
|
oleClientSite2.GetContainer( out pObj);
|
object [] args = new object [1];
|
IHTMLDocument pDoc2 = (IHTMLDocument)pObj;
|
object script = pDoc2.Script;
|
//调用JavaScript方法OnScaned并传递参数,因为此方法可能并没有在页面中实现,所以要进行异常处理
|
script.GetType().InvokeMember( "ShowNowTime" , BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
|
点击按钮时的操作:
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void button1_Click( object sender, EventArgs e)
|
CallJavaScript( this .label2.Text);
|
(4)网页中的javascript
function ShowNowTime(nowtime) {
|
alert( "当前时间:" + nowtime);
|
卸载原来的ActiveX控件,重新安装,实际效果:
参考:http://blog.csdn.net/sabty/archive/2009/05/10/4165342.aspx
这篇文档到这里就结束了,关于这两个方法的使用,如果有问题,欢迎和我交流!
分类:
C#2011-05-27 15:53 316人阅读
评论(0)
收藏 举报
这篇文章将介绍ActiveX版本更新的方法,参考了我最初文章中一位朋友的回复中的方法。通过设置注册表中的的ActiveX的版本(InstalledVersion)来维护更新。
1、更新Activex的版本:
(1)在ActiveX项目上点右键,属性,应用程序,程序集信息,最初的版本是1.0.0.0,修改为1.0.1.0
(2)修改控件,以区别1.0.0.0版本,修改V1.0.0为V1.0.1
(3)然后重新生成。
2、修改安装程序
(1)添加注册表项
在项目上点右键,视图,注册表:
在HKEY_CLASSES_ROOT下创建CLSID/{ActiveX的GUID}/InstalledVersion/,
在InstalledVersion下新建字符串值,修改字符串的值为”1,0,1,0″,
注意:删除名称中的值,自动会显示“(默认值)”,这样才能设置注册表中默认值,不要自己输入“默认值”。
(2)修改安装程序版本
修改Version为”1.0.1″,修改RemovePreviousVersions为”True”。
(3)重新生成安装程序
3、重新制作CAB安装包
cabarc n HelloBossma.cab HelloBossmaSetup.msi install.inf
4、修改网站
(1)将生成的CAB安装包替换原来的安装包。
(2)修改页面控件版本
- <object classid="clsid:636B8CE1-7512-464C-B63C-FC75BDCA21DB" codebase="hellobossma/HelloBossma.CAB#version=1,0,1,0" width="442" height="116" id="HelloBossma" name="HelloBossma">
- </object>
5、最终效果
刷新页面,提示安装新的版本,直接安装就好了。
分类:
C#2011-05-27 15:57 395人阅读
评论(0)
收藏 举报
这一节将测试ActiveX控件在新版操作系统上运行的问题,并提出解决的办法。主要是ActiveX程序兼容性和CAB文件的安装问题。我在Vitual PC上安装了Windows 7,并且使用IE8浏览器。
1、测试环境:Windows 7 + IE8
2、修改之前,直接访问页面看看,发现出错了:
出错行:document.HelloBossma.SetTime(vYear + “-” + vMon + “-” + vDay + ” ” + vHour + “:” + vMin + “:” + vSec)
然后到控制面中没有找到安装的ActiveX程序,结合出错行,大致得出结论:ActiveX没有安装成功!
3、修改文件
install.inf:
run=%EXTRACT_DIR%/run.bat |
新加[Deployment],关于这个项目看:http://msdn.microsoft.com/zh-cn/library/dd433049(en-us,VS.85).aspx
InstallScope=machine 我这里只能用这个,改成user无法安装成功,原因未知。
另外在vista以后的版本只能执行cab中的文件了,所以msiexec转移到了bat中执行,添加一个bat文件。
run.bat:
msiexec.exe /i "%CURDIR%/HelloBossmaSetup.msi" /qn |
4、制作CAB包
重新制作CAB包,添加一个run.bat:
cabarc n HelloBossma.cab HelloBossmaSetup.msi install.inf run.bat |
5、在浏览器安装
输入网址,提示安装,然后出现命令运行框,然后消失。
如果安装成功,会出现控件界面。
6、一个兼容性问题
这时候会发现,浏览器左下角有javascript错误,同时点击Call Javascript发生异常。
无法将类型为“Systerm._ComObject ”的COM对象强制转换为类类型“mshtml.HTMLWindow2Class”。
在XP、Windows Server 2003中都没有问题,Windows 7上出现问题,可能是权限设置问题。
按照上边的提示,找到出现问题的地方:
Default.aspx:
window.onload = function () {
|
document.HelloBossma.SetHtml( this );
|
HelloBossmaActiveX.cs
public void SetHtml(object obj) |
html = (mshtml.HTMLWindow2Class)obj;
|
按照提示,我们可以把它转换为接口试试,在网上找到了HTMLWindow2Class的定义,
public class HTMLWindow2Class : System.__ComObject, MSHTML.IHTMLFramesCollection2, MSHTML.IHTMLWindow2, mshtml.IHTMLWindow3, mshtml.IHTMLWindow4, mshtml.DispHTMLWindow2, mshtml.HTMLWindowEvents_Event, mshtml.HTMLWindowEvents2_Event, mshtml.HTMLWindow2
|
经过测试,IHTMLWindow2定义了execScript,所以修改SetHtml为:
private mshtml.IHTMLWindow2 html = null ;
|
public void SetHtml(object obj) |
html = obj as mshtml.IHTMLWindow2;
|
如果你需要其它的方法,换换接口试试。
重新编译,重新安装控件,OK了!
转自:http://blog.bossma.cn/dotnet/visual-studio-2008-csharp-activex-summary-4/
-
C# 在 vs2010 上开发 ActiveX 控件 【千辛万苦啊~】
由于B/S项目中需要使用到读卡器的功能,但是由于厂家只有提供一个 读卡的dll,那么怎样能在客户端使用读卡器呢,那么进过一番查找,最总决定使用ActiveX 控件来做.由于是第一次接触到 Active ...
-
在此页上的ActiveX控件和本页上的其他部分的交互可能不安全,你想允许这种交互吗
转自 http://www.cnblogs.com/zdxster/archive/2011/01/27/1945868.html 在EOS6的项目中,如果采用VC++开发的ActiveX,那么第一次 ...
-
Matlab安装记录 - LED Control Activex控件安装
Matlab安装记录-LED Control Activex控件安装 2013-12-01 22:06:36 最近在研究Matlab GUI技术,准备用于制作上位机程序:在Matlab GUI的技术 ...
-
COM组件开发实践(七)---多线程ActiveX控件和自动调整ActiveX控件大小(上)
声明:本文代码基于CodeProject的文章<A Complete ActiveX Web Control Tutorial>修改而来,因此同样遵循Code Project Open L ...
-
如何用ATL创建ActiveX控件
演示截图: 代码简介或代码解析: 如何用ATL创建ActiveX控件 实现了一个ActiveX控件,它在一个圆内部有个正多边形,当用户在多变形内部单击将会使多边形的边数在当前的基础上+1,在多变形外部 ...
-
VS2010 开发 VB6.0 activeX控件 dll
项目源码 https://download.csdn.net/download/csdn_z_s/10427764 开发环境 操作系统: win7 64位 旗舰版 Java语言开发环境: Eclip ...
-
Delphi发布ActiveX控件 制作CAB包 数字签名相关
文件: SignTool.rar 大小: 84KB 下载: 下载 最近我正在研究ActiveX技术.我使用Delphi 7创建了一个具有ActiveForm的ActiveX控件应用程序.这个控件产生一 ...
-
OLE、OCX和ActiveX控件之间的比较
OLE(Object Linking and Embedding,对象连接与嵌入) 一.过去的OLE和今天的OLE 最初的OLE含义是指在程序之间链接和嵌入对象数据,它提供了建立混合文档的手段(资 ...
-
盗墓笔记—阿里旺旺ActiveX控件imageMan.dll栈溢出漏洞研究
本文作者:i春秋作家——cq5f7a075d 也许现在还研究Activex就是挖坟,但是呢,笔者是摸金校尉,挖坟,呸!盗墓是笔者的本职工作. 额,不扯了,本次研究的是阿里旺旺ActiveX控件imag ...
-
Nova PhoneGap框架 总结
Nova PhoneGap Framework 是完全针对PhoneGap应用程序量身定做的,在这个框架下开发的应用程序很容易实现高质量的代码,很容易让程序拥有很好的性能和用户体验. 在经历了多个项目 ...
-
测试Python代码
作为程序员,懂得测试,这是必须的职业技能.很遗憾,我以前从未意识到这点,因此经历了很多叫苦不迭的开发生涯.当然了,期望每个人都成为测试高手也是不可能的,但是最基本的单元测试啥的是不惜的,尤其是现在中小 ...
-
常用库nuget包集合
ColorConsole htmlagilitypack.1.4.9.5 经测试效率比 CsQueryLaster 高 csvhelper Extend Devlib系列一套 itextsharp l ...
-
PUT 还是 POST ?
http://www.oschina.net/translate/put-or-post http://my.oschina.net/u/1263964/blog/268932 这两个方法咋一看都可以 ...
-
leetcode_438_Find All Anagrams in a String_哈希表_java实现
题目: Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Stri ...
-
linux 系统运行级别及修改[转]
Linux运行级别从0-6,共7个. 0:关机.不能将系统缺省运行级别设置为0,否则无法启动. 1:单用户模式,只允许root用户对系统进行维护. 2:多用户模式,但不能使用NFS(相当于Window ...
-
Scut:Redis 资源管理器
核心文件是:RedisConnectionPool.cs 对象池类的通用泛型封装:ObjectPoolWithExpire<T> 1. 主要变量 private static ICache ...
-
iostransitiontranslate闪屏问题总结
webkit在绘制页面时会将结构分为各种层,当层足够大时就会变成很大的平铺层.这样一来webkit在每次页面结构发生变化时不需要都渲染整个页面而是渲染对应层了,这对渲染速度来说相当的重要.webkit ...
-
php simpleXML操作xml的用法
XML简介 XML是一种流行的半结构化文件格式,以一种类似数据库的格式存储数据.在实际应用中,一些简单的.安全性较低的数据往往使用 XML文件的格式进行存储.这样做的好处一方面可以通过减少与数据库的交 ...
-
sql语句转为Model
在跟数据库打交道的时候,有一个常用的应用,就是把数据库中的表转为程序中的对象,也就是说表中的列转为对象的属性.对于字段比较少的,我们可以直接复制过去改,但是字段数比较多的时候,借助工具类实现比较方便而 ...