C#制作、打包、簽名、發布Activex全過程

一、前言

????? 最近有這樣一個需求,需要在網頁上面啟動客戶端的軟件,軟件之間的通信、調用,單單依靠HTML是無法實現了,因此必須借用Activex來實現。由于本人主要擅長C#,自然本文給出了用C#實現的范例,本文的預期效果是有一定Winform基礎的人可都輕松讀懂本文。

文章主要介紹了以下幾個部分:
1、用C#制作Activex控件,并發布為msi安裝文件
2、將msi打包為cab,達到瀏覽器自動安裝的效果
3、給cab數字簽名(可選)
4、將Activex應用到網頁上
二、用C#制作Activex控件,并發布為msi安裝文件
1)新建window用戶控件項目EasyActivex。其實VS2010并沒有提供專門的Activex項目模板,所謂的Activex,只要符合com標準即可。
2)在EasyActivex項目添加IObjectSafety接口
在IObjectSafety接口代碼如下,值得注意的是Guid不能隨便改,必須為一下代碼給出的Guid:
復制代碼
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;namespace EasyActivex
{[ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")][InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]public interface IObjectSafety{[PreserveSig]int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);[PreserveSig()]int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);}
}
復制代碼

?

3)在EasyActivex項目添加EUserControl控件,在控件中實現IObjectSafety接口。
在控件上面添加按鈕,命名為btnOpenNote
控件的后臺代碼必須實現IObjectSafety接口
復制代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace EasyActivex
{//這個Guid,網頁調用的時候用到,Mark[Guid("685F0A47-944D-4145-BF4E-76A02A422B02")]//這里要實現IObjectSafety接口public partial class EUserControl : UserControl, IObjectSafety  {public EUserControl(){InitializeComponent();}#region 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 int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions){int Rslt = E_FAIL;string strGUID = riid.ToString("B");pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;switch (strGUID){case _IID_IDispatch:case _IID_IDispatchEx:Rslt = S_OK;pdwEnabledOptions = 0;if (_fSafeForScripting == true)pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;break;case _IID_IPersistStorage:case _IID_IPersistStream:case _IID_IPersistPropertyBag:Rslt = S_OK;pdwEnabledOptions = 0;if (_fSafeForInitializing == true)pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;break;default:Rslt = E_NOINTERFACE;break;}return Rslt;}public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions){int Rslt = E_FAIL;string strGUID = riid.ToString("B");switch (strGUID){case _IID_IDispatch:case _IID_IDispatchEx:if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))Rslt = S_OK;break;case _IID_IPersistStorage:case _IID_IPersistStream:case _IID_IPersistPropertyBag:if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))Rslt = S_OK;break;default:Rslt = E_NOINTERFACE;break;}return Rslt;}#endregion/// <summary>/// 打開記事本/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnOpenNote_Click(object sender, EventArgs e){System.Diagnostics.Process.Start("notepad.exe"); }}
}
復制代碼

小提示:EUserControl代碼的Guid可以用VS附帶的Guid生成工具生成:

4)在EasyActivex項目AssemblyInfo.cs文件中添加代碼
//用戶添加
[assembly: AllowPartiallyTrustedCallers()]

?

5)設置EasyActivex項目項目屬性為com互操作
6)新建windows程序安裝項目EasySetup
7)將EasyActivex項目生產的dll添加到EasySetup項目中。下圖的EasyActivex.dll為已經添加進去了的文件。
8)在EasySetup項目中,設置EasyActivex.dll文件屬性為vsdraCOM。
完成以上步驟,生成下即可得到msi安裝文件
三、將msi安裝文件打包為cab,達到在瀏覽器中自動安裝的效果
如果只是生成了msi文件,用戶安裝的時候比較麻煩,像安裝一般軟件一樣,需要用戶慢慢點擊下一步,慢慢安裝,在本項目中采用打包成cab文件的方式,做到用戶點擊運行后,即可自動安裝。
在這里需要準備文件有:
cabarc.exe:微軟提供的cab打包工具
EasySetup.msi: ?本案例中EasySetup項目生成的windows部署安裝文件
install.inf : 需要跟EasySetup.msi打包在一起的文件,制作方法請見下文
build.bat: ?打包的批處理命令,制作方法請見下文
1)? install.inf制作。新建txt文件,加入以下內容,將文件名重新命名為install.inf即可。其中EasyZSetup.msi即是要打包的安裝程序的名稱。
復制代碼
[version]  
signature="$CHICAGO$"  
AdvancedINF=2.0  [Setup Hooks]  
hook1=hook1  [hook1]  
run=msiexec.exe /i "%EXTRACT_DIR%\EasySetup.msi" /qn 
復制代碼

?

2)?? build.bat制作。新建txt文件,加入以下內容,將文件名重新命名build.bat即可。其中EasyActivex.cab是生成目標cab的名稱;install.inf是第一步生成的文件名,而EasySetup.msi是需要打包的安裝程序名;第二條ping命令僅僅是讓批處理不要那么快退出,起到更利于觀察生成結果的作用。

"cabarc.exe" -s 6144 n EasyActivex.cab install.inf EasySetup.msi
ping -n 20 127.0.0.1 >nul 

?

把以上四個文件復制到同一個文件夾中,雙擊build.bat批處理命令即可生成cab文件
雙擊bat后的運行結果如下,其中EasyActivex.cab即是生成的目標cab文件。
三、給cab數字簽名(可選)
由于處于安全問題考慮,IE瀏覽器設置默認是禁用未簽名的Activex控件的,不過想想也知道,假如打開個未知網頁,“網頁”就能隨便調用計算機本地的東西是多么恐怖的事情,因此,瀏覽器運行的Activex必須是簽名了的,也符合常理。
如果不怕用戶麻煩,不采用cab簽名的方式的話,也可以通過設置瀏覽器安全性來運行Activex。設置方法:打開瀏覽器--瀏覽器Internet選項--安全選項卡--自定義級別按鈕-下載未簽名的Activex控件設置為提示,保存即可。等安裝完畢后,可以將“下載未簽名的Activex控件”設置回禁用。
以下為給cab簽名的方法,具體方法,數字認證網上面已經介紹得很詳細:
1)申請、安裝證書。上中國數字認證網(http://www.ca365.com/)申請一個免費數字證書(試用期為1年,如果企業用的話需要購買)。?
操作方法:http://www.ca365.com/forward.do?pageurl=/ca/yhsc/4.jsp?,值得注意的是證書用途必須選擇代碼簽名證書。
申請成功后的證書,由于是不帶密鑰的,因此下載完畢后只能夠在申請證書的機器上安裝、使用(簽名文件),如果需要在其他機器上使用的話需要將密鑰導出,操作方法為:?http://www.ca365.com/forward.do?pageurl=/ca/yhsc/5.jsp?。
2)用證書給cab包簽名:http://www.ca365.com/forward.do?pageurl=/ca/thsc/7.jsp?
四、在解決方案中添加EasyWeb項目
終于到了最后一步,發布鳥。在解決方案中添加EasyWeb項目
?
在網頁目錄中新建Activex文件夾,并將EasyActivex.cab文件拷貝進去
在網頁中添加以下代碼,即可調用Activex控件了。值得注意的是codebase是cab包的相對路徑;clsid是EUserControl控件的Guid。
 <object id="csharpActiveX" codebase="Activex/EasyActivex.cab" classid="clsid:685F0A47-944D-4145-BF4E-76A02A422B02"></object>

運行效果如下:

點擊即可在網頁中打開記事本了。

?

五、本案例源碼+cab打包工具+數字簽名工具下載

?

六、參考資料:

1、使用C#開發ActiveX控件 ?http://www.cnblogs.com/yilin/archive/2009/09/15/1567332.html?

2、Activex簽名方法和工具技巧??http://www.360doc.com/content/10/0901/15/203871_50402416.shtml

3、中國數字認證網用戶手冊?http://www.ca365.com/forward.do?pageurl=/ca/yhsc.jsp

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388159.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388159.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388159.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用Python創建漂亮的交互式可視化效果

Plotly is an interactive Python library that provides a wide range of visualisations accessible through a simple interface.Plotly是一個交互式Python庫&#xff0c;通過簡單的界面即可提供廣泛的可視化效果。 There are many different visualisation libraries avai…

CCF 201809-1 買菜

問題描述| 試題編號&#xff1a; | 201809-2 | | 試題名稱&#xff1a; | 買菜 | | 時間限制&#xff1a; | 1.0s | | 內存限制&#xff1a; | 256.0MB | 問題描述 小H和小W來到了一條街上&#xff0c;兩人分開買菜&#xff0c;他們買菜的過程可以描述為&#xff0c;去店里買一…

筆試題③

1.線程間通信 handler機制 2.AsyncTask 異步任務 3.HandlerThread 子線程中創建了一個 Looper對象 可以在子線程里使用消息機制 IntentService 帶了HandlerThread 并且創建了一個子線程的handler 在服務中 創建子線程執行耗時操作 耗時操作執行結束之后服務退出 如果想在Serv…

Hadoop 2.0集群配置詳細教程

Hadoop 2.0集群配置詳細教程 前言 Hadoop2.0介紹 Hadoop是 apache 的開源 項目&#xff0c;開發的主要目的是為了構建可靠&#xff0c;可拓展 scalable &#xff0c;分布式的系 統&#xff0c; hadoop 是一系列的子工程的 總和&#xff0c;其中包含 1. hadoop common &#xff…

php如何減緩gc_管理信息傳播-使用數據科學減緩錯誤信息的傳播

php如何減緩gcWith more people now than ever relying on social media to stay updated on current events, there is an ethical responsibility for hosting companies to defend against false information. Disinformation, which is a type of misinformation that is i…

[UE4]刪除UI:Remove from Parent

同時要將保存UI的變量清空&#xff0c;以釋放占用的系統內存 轉載于:https://www.cnblogs.com/timy/p/9842206.html

MySQL基礎部分總結

MySQL 1、選擇數據庫 use dbnameshow databases;2、數據表 show tablesmysql> show columns from customers;mysql> desc customers;3、show 語句 show statusshow create databasesshow create tableshow grants4、select 檢索 4.1.1版本后不再區分大小寫&#xff0c;但…

BZOJ2503: 相框

Description P大的基礎電路實驗課是一個無聊至極的課。每次實驗&#xff0c;T君總是提前完成&#xff0c;管理員卻不讓T君離開&#xff0c;T君只能干坐在那兒無所事事。先說說這個實驗課&#xff0c;無非就是把幾根導線和某些元器件&#xff08;電阻、電容、電感等&#xff09;…

泰坦尼克號 數據分析_第1部分:泰坦尼克號-數據分析基礎

泰坦尼克號 數據分析My goal was to get a better understanding of how to work with tabular data so I challenged myself and started with the Titanic -project. I think this was an excellent way to learn the basics of data analysis with python.我的目標是更好地了…

Imperva開源域目錄控制器,簡化活動目錄集成

Imperva已公開發布域目錄控制器&#xff08;Domain Directory Controller&#xff0c;DDC&#xff09;的源代碼&#xff0c;這是一個Java庫&#xff0c;用于簡化常見的Active Directory集成。 與Java的LdapContext不同&#xff0c;這個庫構建在Apache Directory LDAP之上&#…

2018.10.24 NOIP模擬 小 C 的序列(鏈表+數論)

傳送門 考慮到a[l],gcd(a[l],a[l1]),gcd(a[l],a[l1],a[l2])....gcd(a[l]...a[r])a[l],gcd(a[l],a[l1]),gcd(a[l],a[l1],a[l2])....gcd(a[l]...a[r])a[l],gcd(a[l],a[l1]),gcd(a[l],a[l1],a[l2])....gcd(a[l]...a[r])是可以分成最多logloglog段且段內的數都是相同的。 那么我們用…

vba數組dim_NDArray — —一個基于Java的N-Dim數組工具包

vba數組dim介紹 (Introduction) Within many development languages, there is a popular paradigm of using N-Dimensional arrays. They allow you to write numerical code that would otherwise require many levels of nested loops in only a few simple operations. Bec…

Nodejs教程08:同時處理GET/POST請求

示例代碼請訪問我的GitHub&#xff1a; github.com/chencl1986/… 同時處理GET/POST請求 通常在開發過程中&#xff0c;同一臺服務器需要接收多種類型的請求&#xff0c;并區分不同接口&#xff0c;向客戶端返回數據。 最常用的方式&#xff0c;就是對請求的方法、url進行區分判…

關于position的四個標簽

四個標簽是static&#xff0c;relative&#xff0c;absolute&#xff0c;fixed。 static 該值是正常流&#xff0c;并且是默認值&#xff0c;因此你很少看到&#xff08;如果存在的話&#xff09;指定該值。 relative&#xff1a;框的位置能夠相對于它在正常流中的位置有所偏移…

python算法和數據結構_Python中的數據結構和算法

python算法和數據結構To至 Leonardo da Vinci達芬奇(Leonardo da Vinci) 介紹 (Introduction) The purpose of this article is to give you a panorama of data structures and algorithms in Python. This topic is very important for a Data Scientist in order to help …

CSS:元素塌陷問題

2019獨角獸企業重金招聘Python工程師標準>>> 描述&#xff1a; 在文檔流中&#xff0c;父元素的高度默認是被子元素撐開的&#xff0c;也就是子元素多高&#xff0c;父元素就多高。但是當子元素設置浮動之后&#xff0c;子元素會完全脫離文檔流&#xff0c;此時將會…

Celery介紹及常見錯誤

celery 情景&#xff1a;用戶發起request&#xff0c;并等待response返回。在本些views中&#xff0c;可能需要執行一段耗時的程序&#xff0c;那么用戶就會等待很長時間&#xff0c;造成不好的用戶體驗&#xff0c;比如發送郵件、手機驗證碼等。 使用celery后&#xff0c;情況…

python dash_Dash是Databricks Spark后端的理想基于Python的前端

python dash&#x1f4cc; Learn how to deliver AI for Big Data using Dash & Databricks this recorded webinar with Peter Kim of Plotly and Prasad Kona of Databricks.this通過Plotly的Peter Kim和Databricks的Prasad Kona的網絡研討會了解如何使用Dash&#xff06…

js里的數據類型轉換

1、類型轉換 轉換為字符串 - String(x)- x.toString(x, 10)- x 轉換為數字 - Number(x)- parseInt(x, 10) - parseFloat(x) - x - 0- x 轉換為boolean - Boolean(x)- !!x 2、falsy值&#xff08;false&#xff09; - 0- NaN- - null- undefined 3、內存圖 - object存儲的是地址…

Eclipse 插件開發遇到問題心得總結

Eclipse 插件開發遇到問題心得總結 Posted on 2011-07-17 00:51 季楓 閱讀(3997) 評論(0) 編輯 收藏1、Eclipse 中插件開發多語言的實現 為了使用 .properties 文件&#xff0c;需要在 META-INF/MANIFEST.MF 文件中定義&#xff1a; Bundle-Localization: plugin 這樣就會…