用C#編寫ActiveX控件javascript
http://www.cnblogs.com/homer/archive/2005/01/04/86473.html http://www.cnblogs.com/homer/archive/2005/01/08/88780.html http://www.cnblogs.com/homer/archive/2005/01/26/97822.html http://www.cnblogs.com/xiaoshatian/archive/2008/09/02/1281786.html 用C#編寫ActiveX控件(一) 前些日子作一個Web項目,必須本身編寫一個ActiveX控件。現在的ActiveX控件大可能是使用VB/C++來開發的,而我對他們並不熟悉,所以考慮使用熟悉的C#編寫ActiveX控件。 首先,創建一個WinForm控件項目HelloWorld,並拖入一個Label控件,文字設爲HelloWorld,如圖: UserControl1.cs內容以下: using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; namespace HelloWorld { /// <summary> /// UserControl1 的摘要說明。 /// </summary> public class Demo : System.Windows.Forms.UserControl { private System.Windows.Forms.Label label1; /// <summary> /// 必需的設計器變量。 /// </summary> private System.ComponentModel.Container components = null; public Demo() { // 該調用是 Windows.Forms 窗體設計器所必需的。 InitializeComponent(); // TODO: 在 InitComponent 調用後添加任何初始化 } /// <summary> /// 清理全部正在使用的資源。 /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } 組件設計器生成的代碼 } } 此時編譯項目,能夠生成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查看,咱們的控件又能夠在網頁中顯示了。不過,這個時候它已經再也不是之前的.net WinForm控件了,而是貨真價實的ActiveX控件了。 不過,編寫ActiveX控件的任務尚未完成。咱們尚未實現腳本互動或者讀寫I/O,也沒有實現ActiveX控件的自動分發。在下一篇Blog中,我會完成ActiveX控件的編寫。 PS:這是我在博客園上的第一個Post,但願獲得你們的支持。 用C#編寫ActiveX控件(二) Homer 在個人上一篇blog中,已經實現了一個最基本的ActiveX控件。固然,咱們編寫的任務尚未完成。首先,咱們先嚐試實現和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 成員 從新編譯,而後將IE裏面的設置改回來。如今,咱們發現,和JS的交互已經沒有問題了。 這樣,一個最基本的ActiveX控件已經寫好了。你能夠在這個控件的基礎上增長任何你須要的功能。到這裏,編寫控件的任務已經完成了,咱們的下一個目標就是發佈它。 用C#編寫ActiveX控件(三) 在前面咱們已經完成了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》。先給給你們提個醒,在申請證書的時候選擇 高級證書申請。 至此,《用C#編寫ActiveX控件》完結。你們有什麼問題,能夠和我留言。 在用c#開發的ActiveX中調用JavaScript方法 2008-09-02 09:57 by Windie Chai, 7949 visits, 收藏, 編輯 這段時間要寫一個ActiveX控件來控制掃描儀,並在掃描完成以後將文件路徑通知頁面。由於掃描的過程是異步的,因此我不能利用ActiveX控件公開的Scan方法來返回文件路徑,結合Name Ctrl訂閱聯繫人狀態的思路,我想,若是能夠用JavaScript來訂閱ActiveX完成掃描的「事件」,我就能夠在這個「事件」中把文件路徑看成參數傳遞給頁面了。 關於如何用c#開發ActiveX控件,紅馬天下兄的系列文章寫的很是不錯,我這裏主要講一下如何在ActiveX中調用頁面上的JavaScript方法。 1.引用Microsoft.mshtml Microsoft.mshtml的路徑是C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll,添加引用後在ActiveX對應類中編寫: using mshtml; 2.用c#實現兩個COM類,IOleClientSite和IOleContainer [ComImport, Guid("00000118-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IOleClientSite { void SaveObject(); void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk); void GetContainer(out IOleContainer ppContainer); void ShowObject(); void OnShowWindow(bool fShow); void RequestNewObjectLayout(); } [ComImport, 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, [In, 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.調用JavaScript方法 在Activex控件的對應類中就能夠編寫以下的CallJavaScript方法: private void CallJavaScript(string Filenames) { Type typeIOleObject = this.GetType().GetInterface("IOleObject",true); object oleClientSite = typeIOleObject.InvokeMember("GetClientSite", BindingFlags.Instance|BindingFlags.InvokeMethod|BindingFlags.Public, null, this, null); IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite; IOleContainer pObj; oleClientSite2.GetContainer(out pObj); //參數數組 object[] args = new object[1]; args[0] = Filenames; //獲取頁面的Script集合 IHTMLDocument pDoc2 = (IHTMLDocument)pObj; object script = pDoc2.Script; try { //調用JavaScript方法OnScaned並傳遞參數,由於此方法可能並無在頁面中實現,因此要進行異常處理 script.GetType().InvokeMember("OnScaned", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, script, args); } catch { } } 4.在頁面中實現相應的JavaScript方法 在包含這個ActiveX控件的頁面中添加以下的JavaScript方法: <script type="text/javascript"> function OnScaned(files) { if(files) { //do something } } </script> 這樣,在ActiveX控件中調用CallJavaScript方法時,最終就會調用到頁面中的OnScaned方法,藉此實現了ActiveX的「事件」機制。 在測試的過程當中發現一些有趣的事情,不妨也和你們分享一下: 1. object元素的結束:object元素只能以<object></object>的方式結束,而不能簡單的用<object/>來結束,這樣結束的後果是object後邊的元素都沒法在JavaScript方法中獲取,多是瀏覽器還認爲object元素沒有結束吧。 2. 參數的類型:最初我想在c#中給JavaScript方法傳遞數組類型的參數,但當JavaScript方法執行時,我發現JavaScript將該參數識別爲「unknown」,而且沒法對其作任何處理,因此最後只好做罷,用傳遞以「|」分隔的字符串代替。 3. 小草的這篇文章提供了更簡單的調用JavaScript方法,只須要在初始化時傳遞頁面的window屬性,但我還沒弄清楚如何給JavaScript傳遞參數。 原文發佈於coding.windstyle.cn,歡迎訪問、訂閱並和我交流。
用C#編寫ActiveX控件,開發瀏覽器控件,註冊ActiveX 控件html
用C#編寫ActiveX控件,開發瀏覽器控件,註冊ActiveX 控件 用C#編寫ActiveX控件 開發瀏覽器控件這是本控件開發完成後的一個簡單應用。咱們能夠利用它以本地文件夾爲單位來批量更新服務器的文件。多線程文件夾上傳實現 最近作一個Web項目,須要本身編寫一個ActiveX控件。ActiveX控件大可能是使用C++來開發的,而我對他們並不熟悉,所以考慮使用熟悉的C#編寫ActiveX控件。 ActiveX 控件註冊 首先,創建一個Windows控件庫 項目 My_HtmlControl,並拖入一個textBox控件,此時編譯項目,能夠生成My_HtmlControl.dll。將此dll拷貝到IIS的虛擬根目錄下,而後創建一個aa.htm的文件,html代碼以下: <body> <object classid="http://localhost/My_HtmlControl.dll#My_HtmlControl.UserControl1" Width="184" Height="96"> </object> </body> 在IE地址欄中輸入如下地址:http://localhost/aa.htm,出現界面:可見textBox控件文本框 控件已經成功在頁面上顯示了。OK,咱們已經完成了第一步。 可是問題到這裏尚未解決。不相信?你能夠試試在另一臺機器上測試,注意須要修改對應的html代碼和URL地址。你能夠看到這個在原來顯示控件的地方是一個紅色的叉,或者還會彈出一個對話框,表示這個控件沒有任何權限。出現這個結果是微軟的默認設置形成的,做者必須在控件所在的控件的 AssemblyInfo.cs/vb 中執行一個安全聲明,聲明這個控件必須使用賦予的權限,才能夠顯示出界面。 在AssemblyInfo.cs中using System.Security;命名空間,並添加一句: [assembly : AllowPartiallyTrustedCallers()] 註冊ActiveX 控件如今從新編譯,而且替換之前的dll,界面又能夠顯示出來了。 須要提醒的是,到如今爲止,咱們編寫的還不是真正的ActiveX控件。這個控件到如今爲止,還只是可以實現自身的顯示,而且不能實現更多的功能,好比實現與腳本的交互或者操做客戶端的註冊表或者磁盤。這是因爲.Net Framework的安全模型所限制的。若是咱們但願這個控件突破.Net Framework安全模型的限制,實現與腳本的交互或者操做客戶端的註冊表或者磁盤的話,必需要讓它成爲真正的ActiveX控件。下面,咱們把剛纔的控件變成真正的ActiveX控件。 首先使用 工具—〉建立GUID 生成一個GUID, 並修改UserControl1.cs文件。首先using System.Runtime.InteropServices;命名空間,並在public class UserControl1 : System.Windows.Forms.UserControl前面加入一條語句類標記:[Guid("93210714-D354-4e64-96A7-2DA3BE0E16BC")] 注意Guid中的字符串,就是你生成的Guid字符串。它是你所生成的ActiveX控件的惟一標識符。而後修改項目屬性,打開項目屬性面板->配置屬性->生成,將最後一項「爲Com Interop註冊」,咱們惟一須要修改的是將其值改成True。 從新編譯。咱們使用 工具—〉OLE/COM對象查看器 查看,展開.NET Category 找到My_HtmlControl.UserControl1 能夠看到,咱們寫的My_HtmlControl.UserControl1已經被正確識別爲COM組件。如今,咱們已經能夠像使用其它ActiveX控件同樣在網頁中顯示了。在My_HtmlControl.UserControl1點擊鼠標右鍵,選擇Copy HTML <object> Tag to Clipboard,能夠將代碼拷入剪貼板。 如今,咱們改寫aa.htm,html代碼以下: <body> <object id="My_HtmlControl" classid="clsid:93210714-D354-4E64-96A7-2DA3BE0E16BC"></object> </body> 使用IE查看,咱們的控件又能夠在網頁中顯示了。不過,這個時候它已經再也不是之前的.net WinForm控件了,而是貨真價實的ActiveX控件了。 不過,編寫ActiveX控件的任務尚未完成。咱們尚未實現腳本互動或者讀寫I/O,也沒有實現ActiveX控件的自動分發。下面嘗試實現和JS的交互:(在UserControl1.cs中添加) public void ShowMessage(string msg) { if(msg != null) { MessageBox.Show(msg); } } 從新編譯 修改html代碼:添加 <input type="button" onclick='My_HtmlControl.ShowMessage('Hello World!')' value='Click'> 訪問咱們的html頁,就是提示不安全信息。 單擊肯定以後,咱們發現JS報錯。根據提示,咱們判斷能夠經過修改IE的設置使控件運行。打開IE的 工具->Internet選項->安全->本地Intranet->自定義級別->對沒有標記爲安全的ActiveX控件進行初始化和運行,將其值設爲啓用。咱們刷新頁面,如今終於能夠正確運行了。爲何會報錯呢??? 這是由於咱們必需要實現IObjectSafety接口,把ActiveX控件標記爲安全的ActiveX控件。 首先咱們本身用C#實現這個接口:(在UserControl1.cs中添加) public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions) { // TOD 添加 WebCamControl.GetInterfacceSafyOptions 實現 pdwSupportedOptions = 1; pdwEnabledOptions = 2; } public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions) { // TOD 添加 WebCamControl.SetInterfaceSafetyOptions 實現 } 標記Activex控件爲腳本安全1.見Designing Secure ActiveX Controls,這種方法主要適用於ATL Activex控件,最好仍是用C++來實現的,相對來講比較麻煩; 2.見Marking Business Objects as Safe for Scripting,選用這種方法,則很是簡單了,只須要寫入兩個註冊表項就能夠了,以下: [HKEY_CLASSES_ROOT\CLSID\<MyActiveXGUID>\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}] [HKEY_CLASSES_ROOT\CLSID\<MyActiveXGUID>\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}] 一般ActiveX控件在開發並註冊後,一旦在網頁中運行,IE並不認爲這是一個腳本安全的,會彈出一個IE提示窗口:"An ActiveX control on this page might be unsafe to interact with other parts of the page.Do you want to allow this interaction?" 從新編譯,而後將IE裏面的設置改回來在註冊表裏添加如上兩項。如今,咱們發現,和JS的交互已經沒有問題了。 這樣,一個最基本的ActiveX控件已經寫好了。你能夠在這個控件的基礎上增長任何你須要的功能。到這裏,編寫控件的任務已經完成了,咱們的下一個目標就是發佈它。 首先,咱們創建一個windows安裝項目,在解決方案中添加新項目【安裝項目】 ,並將ActiveX控件的主輸出添加到項目輸出中 。而後,改動ActiveX控件的主輸出文件,將其Register屬性改成vsdrpCOM. 改動項目屬性,將引導程序更改成 Web引導程序。很遺憾的是,在 Web引導程序設置 中的安裝文件夾URL中必須使用絕對路徑,不能使用相對路徑。這意味着生成安裝程序的時候就必須肯定路徑,不是很方便。在示例中,我使用了localhost,在發佈中能夠改成實際的域名。 如今咱們生成安裝程序,並把相應得程序拷貝到正確的目錄中(本例中爲默認網站目錄下的ActiveX文件夾中)。咱們能夠直接執行Setup.Exe文件,以驗證安裝文件的正確性。在個人機器上正確執行了,成功了! <object id="My_HtmlControl" classid="clsid:93210714-D354-4E64-96A7-2DA3BE0E16BC" Width="184" Height="96" codebase="ActiveX/Setup.Exe"> </object> codebase="ActiveX/Setup.Exe" 注意,咱們在object塊中加入了codebase屬性,這就是制定的下載控件的位置,可使用相對路徑。別忙,咱們如今還不能正確請求這個頁面,由於咱們尚未對咱們的控件進行簽名。簽名能夠採用兩種方式,一種是在上面生成安裝程序的時候簽名,另外一種是使用sn.exe簽名。推薦你們使用後者,由於能夠提供更多選項。本人很懶,就很少寫了,你們能夠參考csdn上的文章《發佈ActiveX》。先給給你們提個醒,在申請證書的時候選擇 高級證書申請。 檢查ActiveXObject是否可用,而後引導用戶下載並安裝,有朋友問怎麼自動下載並安裝,我的認爲這種作法不太合適,畢竟ActiveX對用戶來講是存在風險的,因此咱們必需要重視用戶的知情權哦。 var str1 = new Array(); try { var axObj=new ActiveXObject("My_HtmlControl.UserControl1d"); }catch(e){ str1.push("<span class=\"red\"><a style=\"color:#f00;\" href=\"/ActiveX/Setup.Exe\">請點此安裝控件後刷新</a></span>"); document.write(str1.join("")); } alert(DetActiveX()); // 檢測系統是否禁用ActiveX function DetActiveX() { var kXmlHttp = null; try {/*非微軟IE支持的xmlhttp對象*/ if (typeof XMLHttpRequest != "undefined") { kXmlHttp = new XMLHttpRequest(); return true; } else/*微軟IE支持的xmlhttp對象*/ { var MSie = ["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"]; for (i in MSie) { kXmlHttp = new ActiveXObject(MSie[i]); return true; } } }catch(e){} return false; } 針對網友的要求,完善了一下本文的內容 以下在安裝項目上進行設置便可,在安裝軟件時註冊該組件在註冊表中的註冊等操做!以下圖: 對安裝過程當中的全部界面和安裝流程控制均可以定義了。還有一點就是由於是ActiveX全部,安全認證很關鍵。他們和淘寶等網站上的插件是同樣的。若是想要被通用那麼須要認證。創建在信任基礎上讓客戶端安裝應該是最簡單的解決辦法。