精华内容
下载资源
问答
  • 有一个ActiveX控件,在静态的html页面中用<...我把ActiveX的dll用AxImp.exe封装成了WinForm控件,能够显示出来,但是不能运行。然后我想把html用WebBrowser加载,仍然是能够显示但不能运行。请问有什么办法可以解决?
  • winform C#调用Unity3d的Activex
  • 我现在调用vlc activex 插件,能够播放 一个VGA信号器 的信号。 但是我需要把这个信号保存成视频文件,该怎么解决? ``` private void button1_Click(object sender, EventArgs e) { //输入参数 string ...
  • 使用反射动态调用ActiveX控件 袁永福 2018-3-2 ■■■■问题描述: 目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具的添加COM引用时自动...

    使用反射动态调用ActiveX控件

    袁永福 2018-3-2

    ■■■■问题描述:

    目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具的添加COM引用时自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。但会产生额外的程序文件,不利于应用软件的简洁部署。而且当开发环境和运行环境使用的ActiveX控件的版本不一致[袁永福原创]时还容易出错。

    笔者长期从事基于.NET平台的通用产品类软件研发。[袁永福原创]产品类软件要求部署简洁,为此笔者都会将多个工程编译生成的多个.NET程序集文件合并成一个.NET程序集文件来做到简洁部署。

    实践中发现自动生成的互操作性程序集无法合并。另外产品类软件应该能适应各种复杂的开发和生产环境,甚至ActiveX控件的CLSID 都有可能变化。

    例如,对于COM类库“HebcaFormSealLib”,VS.NET会自动生成程序集文件“AxInterop.HebcaFormSealLib.dll”、“Interop.HebcaFormSealLib.dll”。这些程序集文件无法进行程序集合并,而且对于32位或64位的工程项目类型敏感,容易导致错误。

    ■■■■技术改进:

    因此笔者不采用这种自动生成的互操作性程序集。转而采用自定义的反射来调用ActiveX控件。

    后期绑定ActiveX 控件主要知识点为System.Windows.Forms.AxHost类型和Type.InvokeMember方法。

    AxHost类型是从System.Windows.Forms.Control类型[袁永福原创]派生出来的,专门用于承载ActiveX控件。它是一个抽象类,有一个受保护的构造函数,函数参数是一个guid格式的ActiveX控件的CLSID字符串。还有一个GetOcx内部方法用于创建ActiveX控件的对象实例,它是一个COM对象引用。

    创建了这个COM对象引用后就可以调用Type.InvokerMember方法来动态的调用指定名称的方法和属性。

    ■■■■范例:

    笔者最近在使用某电子签名的ActiveX控件来实现文档签名的功能。笔者写出以下接口代码

    [System.Runtime.InteropServices.ComVisible(false)]
    public class DCHebeiCAControl : System.Windows.Forms.AxHost
    {
        public DCHebeiCAControl()
            : base("{e4ee564c-0845-4404-91ee-0c206113333f}")
        { }
    
        public object _ocx = null;
        protected override void AttachInterfaces()
        {
            this._ocx = base.GetOcx();
        }
        private void CheckOCX()
        {
            if (this._ocx == null)
            {
                throw new System.NullReferenceException("_ocx");
            }
        }
        public VersionType GetBaseVersionType()
        {
            this.CheckOCX();
            VersionType result = (VersionType)this._ocx.GetType().InvokeMember(
                "GetBaseVersionType",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { });
            return result;
        }
    
        public string GetCert(string sealSN)
        {
            this.CheckOCX();
            string result = (string)this._ocx.GetType().InvokeMember(
                "GetCert",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { sealSN });
            return result;
        }
    
        public string GetClientDetailVersionInfo()
        {
            this.CheckOCX();
            string result = (string)this._ocx.GetType().InvokeMember(
                "GetClientDetailVersionInfo",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { });
            return result;
        }
    
        public int GetClientVersion()
        {
            this.CheckOCX();
            int result = (int)this._ocx.GetType().InvokeMember(
                "GetClientVersion",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { });
            return result;
        }
    
        public string GetClientVersionInfo()
        {
            this.CheckOCX();
            string result = (string)this._ocx.GetType().InvokeMember(
                "GetClientVersionInfo",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { });
            return result;
        }
    
        public object GetConfig(string argName)
        {
            this.CheckOCX();
            object result = (object)this._ocx.GetType().InvokeMember(
                "GetConfig",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[] { argName });
            return result;
        }
        // ----------- 封装其他接口 -----------------------------
    }//classDCHebeiCAControl
    

     

    上述代码中各个功能函数内部代码结构简单[袁永福原创],之间有很大的相似性,因此完全可以编写一个代码生成器来自动生成上述代码。

    完成自定义的控件后,笔者再创建一个WinForm 窗体,在其Load事件中创建控件并添加到窗体上,其代码如下

    private DCHebeiCAControl _Control = null;
    
    private void frmTest_Load(object sender, EventArgs e)
    {
        this._Control = new DCHebeiCAControl();
        this._Control.Size = new Size(200, 200);
        this._Control.Location = new Point(0, 0);
        this.Controls.Add(this._Control);
    }
    

     

    这样无需使用自动生成的COM接口程序集即可调用ActiveX控件,大幅提高程序的通用性,而且对于32位和64位的项目类型不敏感。方便部署和更新。

    不过这样由于采用后期绑定而带来一定的性能[袁永福原创]问题,因此对于性能敏感而又频繁调用ActiveX控件的场景下需要谨慎采用这种模式。

     

    ■■■■小结:

    在.net开发中调用旧的ActiveX控件是很多开发场景中不得不做的事情。在本文中,笔者介绍了在C#中调用ActiveX控件的标准模式,并提出了一种[袁永福原创]改良模式来提高程序的通用性。为操作ActiveX控件的.NET程序开发提供了一种新的技术手段。

    转载于:https://www.cnblogs.com/xdesigner/p/8504652.html

    展开全文
  • ■■■■前言 ...使用C#调用ActiveX控件时一般是使用vs.net工具自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。...本文就提出使用反射技术动态调用ActiveX控件的方式来解决这些问题。 ...

    ■■■■前言

    目前的基于.NET平台的软件研发中仍然存在大量的对COMActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。但会产生额外的程序文件,不利于应用软件的简洁部署,还容易产生和ActiveX控件版本相关的错误。本文就提出使用反射技术动态调用ActiveX控件的方式来解决这些问题。

     

    ■■■■问题描述:

    目前的基于.NET平台的软件研发中仍然存在大量的对COMActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具的添加COM引用时自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。但会产生额外的程序文件,不利于应用软件的简洁部署。而且当开发环境和运行环境使用的ActiveX控件的版本不一致[袁永福原创]时还容易出错。

    笔者长期从事基于.NET平台的通用产品类软件研发。[袁永福原创]产品类软件要求部署简洁,为此笔者都会将多个工程编译生成的多个.NET程序集文件合并成一个.NET程序集文件来做到简洁部署。

    实践中发现自动生成的互操作性程序集无法合并。另外产品类软件应该能适应各种复杂的开发和生产环境,甚至ActiveX控件的CLSID 都有可能变化。

    例如,对于COM类库“HebcaFormSealLib”,VS.NET会自动生成程序集文件“AxInterop.HebcaFormSealLib.dll”、“Interop.HebcaFormSealLib.dll”。这些程序集文件无法进行程序集合并,而且对于32位或64位的工程项目类型敏感,容易导致错误。

    ■■■■技术改进:

    因此笔者不采用这种自动生成的互操作性程序集。转而采用自定义的反射来调用ActiveX控件。

    后期绑定ActiveX 控件主要知识点为System.Windows.Forms.AxHost类型和Type.InvokeMember方法。

    AxHost类型是从System.Windows.Forms.Control类型[袁永福原创]派生出来的,专门用于承载ActiveX控件。它是一个抽象类,有一个受保护的构造函数,函数参数是一个guid格式的ActiveX控件的CLSID字符串。还有一个GetOcx内部方法用于创建ActiveX控件的对象实例,它是一个COM对象引用。

    创建了这个COM对象引用后就可以调用Type.InvokerMember方法来动态的调用指定名称的方法和属性。

    ■■■■范例:

    笔者最近在使用某电子签名的ActiveX控件来实现文档签名的功能。笔者写出以下接口代码

     
    [System.Runtime.InteropServices.ComVisible(false)]
    public class DCHebeiCAControl System.Windows.Forms.AxHost
    {
        public DCHebeiCAControl()
            base("{e4ee564c-0845-4404-91ee-0c206113333f}")
        }
        public object _ocx null;
        protected override void AttachInterfaces()
        {
            this._ocx base.GetOcx();
        }
        private void CheckOCX()
        {
            if (this._ocx == null)
            {
                throw new System.NullReferenceException("_ocx");
            }
        }
        public VersionType GetBaseVersionType()
        {
            this.CheckOCX();
            VersionType result (VersionType)this._ocx.GetType().InvokeMember(
                "GetBaseVersionType",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[});
            return result;
        }
        public string GetCert(string sealSN)
        {
            this.CheckOCX();
            string result (string)this._ocx.GetType().InvokeMember(
                "GetCert",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[sealSN });
            return result;
        }
        public string GetClientDetailVersionInfo()
        {
            this.CheckOCX();
            string result (string)this._ocx.GetType().InvokeMember(
                "GetClientDetailVersionInfo",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[});
            return result;
        }
        public int GetClientVersion()
        {
            this.CheckOCX();
            int result (int)this._ocx.GetType().InvokeMember(
                "GetClientVersion",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[});
            return result;
        }
        public string GetClientVersionInfo()
        {
            this.CheckOCX();
            string result (string)this._ocx.GetType().InvokeMember(
                "GetClientVersionInfo",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[});
            return result;
        }
        public object GetConfig(string argName)
        {
            this.CheckOCX();
            object result (object)this._ocx.GetType().InvokeMember(
                "GetConfig",
                BindingFlags.InvokeMethod,
                null,
                this._ocx,
                new object[argName });
            return result;
        }
        // ----------- 口 -----------------------------
    }//classDCHebeiCAControl
     

     

    上述代码中各个功能函数内部代码结构简单[袁永福原创],之间有很大的相似性,因此完全可以编写一个代码生成器来自动生成上述代码。

    完成自定义的控件后,笔者再创建一个WinForm 窗体,在其Load事件中创建控件并添加到窗体上,其代码如下

    这样无需使用自动生成的COM接口程序集即可调用ActiveX控件,大幅提高程序 

    private DCHebeiCAControl _Control null;
    private void frmTest_Load(object senderEventArgs e)
    {
        this._Control new DCHebeiCAControl();
        this._Control.Size new Size(200200);
        this._Control.Location new Point(00);
        this.Controls.Add(this._Control);
    }
     

    的通用性,而且对于32位和64位的项目类型不敏感。方便部署和更新。

    不过这样由于采用后期绑定而带来一定的性能[袁永福原创]问题,因此对于性能敏感而又频繁调用ActiveX控件的场景下需要谨慎采用这种模式。

     

    ■■■■小结:

    .net开发中调用旧的ActiveX控件是很多开发场景中不得不做的事情。在本文中,笔者介绍了在C#中调用ActiveX控件的标准模式,并提出了一种[袁永福原创]改良模式来提高程序的通用性。为操作ActiveX控件的.NET程序开发提供了一种新的技术手段。

    转载于:https://www.cnblogs.com/xdesigner/p/8513392.html

    展开全文
  • 1、WinForm引用Adobe PDF Reader 工作中写WinForm程序经常会引用第三方的组件,包括引用Com组件,做了一个桌面程序需要展示PDF,看了些其它的开源组件对PDF的兼容性都不是很好,有些看着PDF是正常的但是复制出来的...

    1、WinForm引用Adobe PDF Reader  

    工作中写WinForm程序经常会引用第三方的组件,包括引用Com组件,做了一个桌面程序需要展示PDF,看了些其它的开源组件对PDF的兼容性都不是很好,有些看着PDF是正常的但是复制出来的字有很多乱码。然后就直接引用了adboe pdf reader来显示,测试了不同pdf兼容性算是不错的。那如何引用呢? 

    • 在工具栏选择项

    • 添加Com组件

    找到Adobe PDF Reader勾选,然后点击确定之后组件就被添加到工具箱里面了。

    • 使用Com组件

    新建一个窗体或者用户控件,将刚才添加的Adobe PDF Reader 组件拖入到窗体中就可以像winform控件一样操作该控件了。

    在该窗体类中生成了一个AxAcroPDFLib.AxAcroPDF的控件,进入该控件类可以看到控件类对外提供的方法,包括用于加载显示pdf的 LoadFile 方法,gotoFirstPage 等翻页的方法。
     

    而该控件有一个父类AxHost类,进入Axhost类有一个摘要:  

    包装 ActiveX 控件,并将它们作为功能完整的 Windows 窗体控件公开  

    对此我陷入了沉思,ActiveX控件到底是什么,com组件如何被使用,AxAxAcroPDFLib.AxAcroPDF类是如何生成的,Winform和Com如何互操作?于是我进行了一番资料查找和学习。

    2、ActiveX控件    

    ActiveX控件技术基于由COM,可连接对象,复合文档,属性页,OLE自动化,对象持久性以及系统提供的字体和图片对象组成的基础。
    控件本质上是一个COM对象,它公开IUnknown接口,客户端可以通过该对象获取指向其其他接口的指针。控件可以通过IClassFactory2和自我注册来支持许可。
    也就是说ActiveX控件是基于COM对象的,使用COM技术让不同语言编写的控件可以进行互相调用,而如何编写ActiveX控件呢,可以使用ATL 和 MFC,但是两个我都没使用过!并且没编写过,所以我就略过,只先了解其概念。既然它是基于COM,那接下来看看COM是什么东东。

     3、COM技术  

     Microsoft组件对象模型(COM)定义了一个二进制互操作性标准,用于创建在运行时进行交互的可重用软件库。您可以使用COM库,而无需将其编译到应用程序中。COM是许多Microsoft产品和技术(例如Windows Media Player和Windows Server)的基础。
    COM定义了适用于许多操作系统和硬件平台的二进制标准。对于网络计算,COM为在不同硬件平台上运行的对象之间的交互定义了标准的有线格式和协议。COM独立于实现语言,这意味着您可以使用其他编程语言(例如C ++和.NET Framework中的编程语言)创建COM库。
    COM规范提供了支持跨平台软件重用的所有基本概念:
    组件之间的函数调用的二进制标准。
    将功能强类型分组到接口中的规定。
    提供多态性,功能发现和对象生存期跟踪的基本接口。
    唯一标识组件及其接口的机制。
    组件加载器,可从部署中创建组件实例。
    COM具有多个部分,这些部分可以一起工作以创建由可重用组件构建的应用程序:
    一个主机系统提供了一个运行时环境符合的COM规范。
    定义要素合同的接口和实现接口的组件。
    为系统提供组件的服务器,以及使用组件提供的功能的客户端。
    一个注册表,用于跟踪组件在本地和远程主机上的部署位置。
    一个服务控制管理器,可以在本地和远程主机上找到组件,并将服务器连接到客户端。
    一种结构化的存储协议,它定义了如何导航主机文件系统上文件的内容。
    跨主机和平台启用代码重用对于COM至关重要。可重用的接口实现被称为组件,组件对象或COM对象。组件实现一个或多个COM接口。
    您可以通过设计库实现的接口来定义自定义COM库。图书馆的使用者可以发现和使用其功能,而无需了解图书馆的部署和实施细节。

    这是官方的定义,当然还有很多细节说明可以看看https://docs.microsoft.com/zh-cn/windows/win32/com/com-technical-overview 其中包括实现的定义和方式,对象和接口、接口实现、IUnknown接口等等。

    那是如何实现如何调用呢,引用一段有趣的概括性的描述:

    COM主要是一套给C/C++用的接口,当然为了微软的野心,它也被推广到了VB、Delphi以及其他一大堆奇奇怪怪的平台上。它主要为了使用dll发布基于interface的接口。我们知道dll的接口是为了C设计的,它导出的基本都是C的函数,从原理上来说,将dll加载到内存之后,会告诉你一组函数的地址,你自己call进去就可以调用相应的函数。
    但是对于C++来说这个事情就头疼了,现在假设你有一个类,我们知道使用一个类的第一步是创建这个类:new MyClass()。这里直接就出问题了,new方法通过编译器计算MyClass的大小来分配相应的内存空间,但是如果库升级了,相应的类可能会增加新的成员,大小就变了,那么使用旧的定义分配出来的空间就不能在新的库当中使用。
    要解决这问题,我们必须在dll当中导出一个CreateObject的方法,用来代替构造函数,然后返回一个接口。然而,接口的定义在不同版本当中也是有可能会变化的,为了兼容以前的版本同时也提供新功能,还需要让这个对象可以返回不同版本的接口。接口其实是一个只有纯虚函数的C++类,不过对它进行了一些改造来兼容C和其他一些编程语言。
    在这样改造之后,出问题的还有析构过程~MyClass()或者说delete myClass,因为同一个对象可能返回了很多个接口,有些接口还在被使用,如果其中一个被人delete了,其他接口都会出错,所以又引入了引用计数,来让许多人可以共享同一个对象。
    其实到此为止也并不算是很奇怪的技术,我们用C++有的时候也会使用Factory方法来代替构造函数实现某些特殊的多态,也会用引用计数等等。COM技术的奇怪地方在于微软实在是脑洞太大了,它们构造了一个操作系统级别的Factory,规定所有人的Interface都统一用UUID来标识,以后想要哪个Interface只要报出UUID来就行了。这样甚至连链接到特定的dll都省了。
    这就好比一个COM程序员,只要他在Windows平台上,调用别的库就只要首先翻一下魔导书,查到了一个用奇怪文字写的“Excel = {xxx-xxx-xxxx...}”的记号,然后它只要对着空中喊一声:“召唤,Excel!CoCreateInstance, {xxx-xxx-xxxx...}”
    然后呼的从魔法阵里面窜出来了一个怪物,它长什么样我们完全看不清,因为这时候它的类型是IUnknow,这是脑洞奇大无比的微软为所有接口设计的一个基类。我们需要进一步要求它变成我们能控制的接口形态,于是我们再喊下一条指令:
    “变身,Excel 2003形态!QueryInterface, {xxx-xxx-xxxx...}”
    QueryInterface使用的是另一个UUID,用来表示不同版本的接口。于是怪物就变成了我们需要的Excel 2003接口,虽然我们不知道它实际上是2003还是2007还是更高版本。
    等我们使唤完这只召唤兽,我们就会对它说“回去吧,召唤兽!Release!”但是它不一定听话,因为之前给它的命令也许还没有执行完,它会忠诚地等到执行完再回去,当然我们并不关心这些细节。(引用地址:https://www.zhihu.com/question/49433640)

    从这个概括理解,所有的COM类其实都继承了IUnknown,当我们拿到IUnknown接口后还需要转成我们需要使用的类型,而这个类型如果用强转可能会出错,但是微软认为,直接由用户来转型是不安全的需要唯一的一个标识符来确定一个类,那么这个标识符就是GUID。类ID就叫作CLSID,接口ID就叫作IID,还需要一个转型的函数叫QueryInterface。QueryInterface作为IUnknown中的一个纯虚函数,做的事情其实很简单,判断自己能不能转成某个GUID所指向的类而已。如果不可以,则返回E_NOTIMPL,可以的话返回S_OK,并将转换后的指针作为参数返回。
    COM组件并不需要名字,或者说不需要UUID,因为我们总是使用他里面的接口,而不是直接使用COM组件,所以接口也要UUID。说了这么多,COM架构这么复杂,肯定需要一个中间层,或者说摆渡人,这就是COM Library(一堆dll) + 注册表。A应用通知COM Library,并输入接口的UUID,由COM Library装入B应用的该组件对应的dll,并把接口指针返回给A应用,指针里指示的是一堆函数指针,由这些指针,可以调用到B应用里的函数功能。

     注:上面有时说的UUID,有时说的GUDI,UUID即是GUID值。

    4、Aximp.exe(Windows 窗体 ActiveX 控件导入程序)  

    有了上面的ActiveX控件和Com组件的介绍,我们再回到开始我们如何导入的ActiveX控件。
    ActiveX 控件导入程序将 ActiveX 控件的 COM 类型库中的类型定义转换为 Windows 窗体控件。
    Windows 窗体只能承载 Windows 窗体控件,即从 Control 派生的类。 Aximp.exe 生成可承载于 Windows 窗体上的 ActiveX 控件的包装器类。 这使你得以使用适用于其他 Windows 窗体控件的同一设计时支持和编程方法。
    若要承载 ActiveX 控件,必须生成从 AxHost 派生的包装器控件。 此包装器控件包含基础 ActiveX 控件的一个实例。 它知道如何与 ActiveX 控件通信,但它显示为 Windows 窗体控件。 这个生成的控件承载 ActiveX 控件并将其属性、方法和事件作为生成的控件的属性、方法和事件公开。  
    由此可见当我们再工具箱里面选择添加com组件后实际隐含执行了该导入程序,为我们生成了对应的AxAcroPDFLib.AxAcroPDF包装器控件。而AxAcroPDFLib则如同第三点中讲的那样就是COM Library。
     5、验证
    既然AxAcroPDFLib 是摆渡人(互操作程序集) 那么我们可以看到这个COM Library的引用

    有了互操作程序那么这个互操作程序必然是去调用COM组件,调用COM组件那么UUID呢?将这个程序集放到Dnspy反编译可以看到在ClsidAttribute标记有{ca8a9780-280d-11cf-a24d-444553540000},构造函数里面有UUID。

    然后我们打开注册表查询下对应的值和注册表的情况。

    6、总结  

    所以通过上面的概念了解和猜想验证,基本清楚了com的设计和想法,以及ActiveX控件的调用过程。

    1.  Activex控件时COM实现的一种方式。
    2.  Activex控件通过VS工具引用时调用了Aximp.exe 。
    3.  Aximp.exe程序生成了互操作程序集AxAcroPDFLib,同时生成可承载于 Windows 窗体上的 ActiveX 控件的从 AxHost 派生的包装器控件。
    4. 调用AxAcroPDF方法时通过com组件调用引用控件的功能。
       
    展开全文
  • Asp.net(c#) b/s通过ActiveX和C# c/s 调用斑马TLP2844条码打印机 通过web打印条码 源代码
  • web页面调用ActiveX

    千次阅读 2015-07-24 14:08:23
    简单总结一下前几篇文章的内容,《浏览器插件之ActiveX开发(一)》简单介绍了一下如何在Vs.net 2008下用C++开发基于MFC的ActiveX插件,《浏览器插件之ActiveX开发(二)》介绍了开发插件时可能遇到的问题,《浏览器...

    原文地址:http://www.cnblogs.com/qguohog/archive/2013/01/25/2876828.html


    简单总结一下前几篇文章的内容,《浏览器插件之ActiveX开发(一)》简单介绍了一下如何在Vs.net 2008下用C++开发基于MFC的ActiveX插件,《浏览器插件之ActiveX开发(二)》介绍了开发插件时可能遇到的问题,《浏览器插件之ActiveX开发(三)》介绍了如何注册插件以及如何打包成cab文件。但是,到目前为止还没有专门提及如何在Web页面中调用插件,本文主要针对这个问题进行展开。

     

    一、用<Object>标签调用ActiveX

        1、Object标签基本用法

        在Html页面中调用ActiveX插件最简单常用的方法是:

    1. <object id="CardAccessor"   
    2.     classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9"       
    3.     width="0"   
    4.     height="0">  
    5. </object>  

      id属性就不用解释了,和html中其他元素的id一样,是DOM树中各元素的唯一标识。width和height表示该ActiveX在Web页面中占位的大小,对于仅提供接口无UI界面的ActiveX来说将其设置为0即可,因为不需要在页面上显示任何内容(对于需要显示界面的ActiveX,需要在项目里创建Dialog及写相应逻辑,可以参考“A Complete ActiveX Web Control Tutorial”实例 )。

        classid属性在这里是一个非常关键的属性,IE正是通过他才能正确找到要调用的ActiveX的。每个ActiveX均有一个唯一的id来表示,这就是classid,在我们创建MFC ActiveX Control项目时Vs.net 2008就帮我们生成了这个id, 可以在程序的.idl文件最下方找到这个ID值:

                 image

         一般不建议手动修改程序中的这个uuid值,因为在xxxxCtrl.cpp文件中也用到了这个id值,只是表现形式不一样罢了:

                image

          控件注册成功后,这个classid及控件文件位置等信息均写入注册表了,如下所示:

                image

          当然,如果ActiveX还定义了其他属性,也可以在<object>中以属性的形式给他们赋值。

     

          如果用户的计算机已经注册了该插件(例如通过Setup.exe方式),那么Html引用上段代码后就可以通过js调用插件的接口和属性了(再次提示一下,ActiveX只能在IE浏览器运行,也就是<object…>这段代码在firefox等其他浏览器是不能正常工作的)。   


    1. <fieldset>  
    2.          <legend>Read Card No Testing</legend>  
    3.          卡号:<input type="text" id="txtCardNo_Read" maxlength="32" class="txt disable" readonly />  
    4.          <input type="button" id="btnRead" value=" Read CardNo " class="btn" onclick="javascript:readCardNo();" />  
    5.     </fieldset>  
    6.       
    7.     <fieldset>  
    8.          <legend>Write Card No Testing</legend>  
    9.          卡号:<input type="text" id="txtCardNo_Write" maxlength="32" class="txt" />  
    10.          <input type="button" id="btnWrite" value=" Write CardNo " class="btn" onclick="javascript:writeCardNo();" />  
    11.     </fieldset>  
    12.   
    13. <script type="text/javascript">  
    14.     var txtCardNo_Read = document.getElementById("txtCardNo_Read");  
    15.     var txtCardNo_Write = document.getElementById("txtCardNo_Write");  
    16.     var objCard = document.getElementById("CardAccessor");  
    17.      
    18.     function readCardNo() {  
    19.         txtCardNo_Read.value = "";  
    20.           
    21.         try{  
    22.             var ret = objCard.ReadCardNo();  
    23.               
    24.             if (ret == 0) {  
    25.                 txtCardNo_Read.value = objCard.CardNo;  
    26.                 alert("读卡成功!");  
    27.             }  
    28.             else {  
    29.                 alert("读卡失败!错误码为:" + ret);  
    30.             }  
    31.         }  
    32.         catch (e) {  
    33.             alert(e.message)  
    34.         }  
    35.     }  
    36.   
    37.     function writeCardNo() {  
    38.         var cardNo = txtCardNo_Write.value;  
    39.   
    40.         try {  
    41.             objCard.CardNo = cardNo;  
    42.             var ret = objCard.WriteCardNo();  
    43.   
    44.             if (ret == 0) {                  
    45.                 alert("写卡成功!");  
    46.             }  
    47.             else {  
    48.                 alert("写卡失败!错误码为:" + ret);  
    49.             }  
    50.         }  
    51.         catch (e) {  
    52.             alert(e.message)  
    53.         }  
    54.     }  
    55.         
    56. </script>  

    [javascript] view plaincopyprint?
    1. <script type="text/javascript">  
    2.     var objCard = document.getElementById("CardAccessor");  
    3.   
    4.     if (objCard.object==null) {  
    5.         alert("CardAccessor插件未安装!");  
    6.     }  
    7.     else{  
    8.         alert("已检测到CardAccessor插件!");  
    9.     }  
    10. </script>  

    [javascript] view plaincopyprint?
    1. <script type="text/javascript">  
    2.     var objCard = document.getElementById("CardAccessor");  
    3.   
    4.     if (objCard.CardNo==undefinedl) {  
    5.         alert("CardAccessor插件未安装!");  
    6.     }  
    7.     else{  
    8.         alert("已检测到CardAccessor插件!");  
    9.     }  
    10. </script>  


      3、如何让IE自动下载安装插件并智能升级

           如果检测到插件没有安装,怎样让IE自动从指定位置下载插件并自动安装呢?很简单,在object标签中使用codebase属性即可:


    <object id="CardAccessor" 
        classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9" 
        codebase="CardAccessor.cab#version=1,0,0,1"
        width="0" 
        height="0">
    </object>

         codebase的值格式为“xxxxx.cab#version=1,0,0,1”。'#'前面部分为cab文件的位置,可以是在服务器上的绝对位置,也可以是相对位置。'#‘后面部分表示当前引用的cab包的版本号。当IE检测到系统没有注册指定插件,便从codebase指定的位置下载该cab到本地,并按照其中.inf文件的描述将各文件复制到指定位置并注册指定的控件。(注:在实际应用中涉及签名问题,后文再述

         即使本地已经注册了该插件,IE还将拿已注册的控件版本号与codebase中指定的版本号相比较,如果codebase中指定的版本号大于已注册插件的版本号,IE仍然会从codebase指定位置下载cab包并重新注册该插件。

         正如前面的文章所提,为方便管理,一般将cab包中需注册的ocx文件的版本号视同cab版本号。

         当插件或插件依赖的文件需要升级时,只需更新相应的文件,并对.inf中的相应文件版本升级(为方便管理,无论是否更新了ocx文件,该ocx文件的版本号也跟着升级,因为其版本号代表了整个cab),然后重新打包成cab发布到服务器上,并更新html中object标签中codebase属性值的version部分版本号。当用户下次访问该页面时,IE将自动下载升级后的cab并重新注册插件。实际上,经过我的测试,及时服务器上的cab包不做任何变化,只要增加codebase中version的值,对应插件均会重新下载和注册。

     

    二、通过javascript的new ActiveXObject来调用ActiveX

          如果不使用object标签,也可以直接通过js的ActiveXObject来创建指定ActiveX的实例从而达到调用插件接口的目的(IE下xmlhttpRequest的调用就是这个原理)。例如:

    [javascript] view plaincopyprint?
    1. var objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");  

          如果插件已经注册,接下来就可以通过objCard来调用插件接口和访问属性了。

          ActiveXObject函数的参数为对应插件的ProgId而非CLASSID。在项目中xxxxCtrl.cpp文件中同样可以找到或修改对应插件的ProgId值,如下图:

           image

         即IMPLEMENT_OLECREATE_EX的第二参数就表示当前插件的ProgId,该值可以根据实际需要自行修改。实际上,在注册表中通过ProgId是可以找到对应的ClassId的,两者是有关联的:

            image

     

          那么如何判断ActiveX是否已经安装呢?实际上如果ActiveX未安装,通过new ActiveXObject的方式来创建插件对象是会抛出“Automation 服务器不能创建对象”异常的。所以用如下方式即可:

    [javascript] view plaincopyprint?
    1. try {  
    2.          objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");                  
    3.     }  
    4. catch (e) {  
    5.          alert("调用ActiveX失败!");  
    6.     }  

       不过,我在实际测试过程中遇到两种情况:

         1) 出现“Automation 服务器不能创建对象”异常的并不一定就表示插件没安装,也有可能是因插件未实现初始化或脚本安全接口,从而被IE拦截,需要调整IE“工具-选项-安全-自定义级别”中“ActiveX控件和插件”部分的设置;

         2) 有时候,同样已注册的插件,通过object标签引用的方式能正常调用接口,但通过new ActiveXObject的方式则调用插件接口失败。



    展开全文
  • C#调用ActiveX控件

    万次阅读 2010-12-02 11:39:00
    在代码中实例化类的实例也没有问题,但在调用其方法或属性时总是抛出"未处理 COMException"异常。   方法一: 1、在系统中注册该ocx控件,命令:regsvr32.exe 控件位置(加 /u 参数是取消注册);...
  • C#写winform调用webservice例子(经典)

    热门讨论 2010-12-01 11:47:31
    vs2005 vs2008皆可 这个是我当初编写Webservice 头一个受益例子现在当然搞定了,感谢当初无名贡献编写者。通过调用一个互联网天气预报的例子可以让大家搞定WebService 。
  • ActiveX控件以前也叫做OLE控件或OCX控件,它是一些软件组件或对象,可以将其插入到WEB网页或其它应用程序中。使用ActiveX插件,可以轻松方便的在 Web页中插入多媒体效果、交互式对象以及复杂程序等等。在Visual ...
  • 用windows服务程序调用activeX控件(二次封装过),达到服务启动时开始录制影音(不需要用窗体显示出来),服务结束时录制结束 。 遇到问题: activeX控件必须加System.Windows.Forms; 而windows服务程序没有,引进...
  • 如上,我依赖于A.ocx编写的B.ocx在mfc和c#里winform都能调用,但是使用网页端js调用的时候,一加载ActiveX控件页面就崩溃退出,没任何消息提示,因为不太懂网页,不知道怎么调试,请问我应该怎么做呢?
  • 前段时间公司做了个比较大的项目,需要用到ocx控件,我厂大部分项目都采用C#.net...笔者此次主要阐述在项目中用javascript调用ocx控件接口,也就是activeX控件时所遇到的问题及其解决方案。winform用法不在此篇中阐...
  • 以前在2.0可以运行的activex控件现在无法正常显示了。 ...建一个winform的demo调用这个容器的话,将参数赋给容器,是能够正常显示的。 现在就不知道为什么调用了不了,有人遇到过这样的问题么?
  • 遇到这个恶心的问题纠缠得不要不要的,大家遇到了的话希望不要走弯路,经过这个折腾让我有点怀疑人生了。哈哈哈 解决代码如下: //插入一个新线程用于处理验证码 Thread thd = new Thread(new ...
  • WinForm调用 Windows 远程桌面

    千次阅读 2012-07-15 13:35:49
     an ActiveX component in our program to connect to the remote computer. It’s not that hard to build a remote desktop application in .NET. Microsoft has a “Microsoft RDP client control” ActiveX ...
  • 首先到微软的网站上下载Windows Script Control,它是一个ActiveX(R) 控件。下载安装完成后,新建一个C#应用程序项目,在解决方案资源管理器中选中引用节点, 右键点击选择添加引用菜单,弹出添加引用对话框,单击...
  • [size=14px]目前在Winform中使用第三方C++编写的OCX控件(ActiveX), 1、已经注册组件(用命令行: Regsvr32 /s [盘符:\][路径\]组件.ocx ) 2、添加引用,并能正常拖动到Form窗体上。 3、 using 命名空间 现在...
  • ScriptControl 对支持 ActiveX(TM) Script 的宿主 Script 引擎提供简单接口。接下来我们对被转化成ScriptControlClass类的ScriptControl的属性和方法进行一些说明。 属性 AllowUI 属性:应用于 ScriptControl ...
  • C#开发的应用程序,如果需要动态加载ActiveX到窗体中,并且要调用指定的方法,网上查了一些,好多都是VB的,C#的偶尔有一些也是要动态加载DLL。    自己研究研究,结果稀里糊涂的弄出来了,话不多说,上代码先: ...
  • ActiveX调用Excel.

    2014-10-15 14:26:22
    Labview调用Excel文件,进行增删改查。
  • 一个winForm程序,加载了一ActiveX控件,用来显示图形,程序编译完成后,在xp下运行正常, 但是在Win7 总是提示 内存位置访问无效,追踪代码报错的位置为: ((System.ComponentModel.ISupportInitialize)(this....
  • 我用WinForm写了一个读卡器,是调用硬件商提供的用C写的dll,运行WinForm没问题,可以读取信息,之后封装成ActiveX控件,就报错了,提示“System.AccessViolationException: 尝试读取或写入受保护的内存。...
  • 下载并安装了VLC2.2.0,在C# winform项目中COM中添加了VLC ,也使用regsvr32注册了axvlc,但是从工具栏中拖控件至窗体时就报未注册,引用这边 显示缺少 AxAXVLC ,如下图,请问是什么原因[img=...[/img]

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,496
精华内容 598
关键字:

winform调用activex