天天看點

C#編寫ActiveX控件

      利用雙休的時間研究了一下c#開發ActiveX控件。由于我用Vs2010開發,參考的文章不是Vs2010和Win7的環境下開發的,中間遇到許多問題,不過總算學到點東西。

我參考的文章如下(非Vs2010開發): 

    用C#編寫ActiveX控件(一)http://www.cnblogs.com/homer/archive/2005/01/04/86473.html

    用C#編寫ActiveX控件(二)http://www.cnblogs.com/homer/archive/2005/01/08/88780.html

    用C#編寫ActiveX控件(三)http://www.cnblogs.com/homer/archive/2005/01/26/97822.html

在我仔細看完上邊三篇文章之後,發現有用Vs2010開發的,如果想快速學習,可以參考下邊的文章。

    .NET環境下建立Activex      http://www.cnblogs.com/liulixiang/archive/2011/05/23/2054371.html

    使用VS2010 C#開發ActiveX控件(上) http://www.cnblogs.com/yungboy/archive/2011/01/10/1932433.html

    使用VS2010 C#開發ActiveX控件(下),完整代碼下載下傳  http://www.cnblogs.com/yungboy/archive/2011/01/11/1932438.html

下邊對學習的内容進行總結,主要是對我參考的文章不足部分進行修改。

一. 建立ActiveX控件(暫時稱為ActiveX控件,其實是winform下的使用者控件)。

1.打開vs2010,建立空年方案。方案名稱自己取。

   然後,建立項目->Visual C#->Windows->類庫,名稱為HelloWorld。

2. 删除自動建立的Class1.cs檔案,然後在HelloWorld上右鍵->添加->建立項,在彈出的視窗中選擇“使用者控件”,名稱為Demo,此時會出現一個類似于winform設計界面,我們在上面從工具箱中拖動一個Label在上面,并設定Label的Text為"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>

    注:我們可以在Object的classid中使用“http://localhost/類.dll#命名空間.類名”這樣的方式使用未注冊的控件(此時還不能稱為ActiveX)。

3、測試:在IE位址欄中輸入以下位址:http://localhost/helloworld.htm,出現下圖界面,控件已經成功在頁面上顯示了。OK,我們已經完成了第一步。

     但是問題到這裡還沒有解決。不相信?你可以試試在另外一台機器上測試,注意需要修改對應的html代碼和URL位址。你可以看到這個在原來顯示控件的地方是一個紅色的叉,或者還會彈出一個對話框,表示這個控件沒有任何權限。出現這個結果是微軟的預設設定造成的,必須在控件項項目中Properties下AssemblyInfo.cs中增加一個安全聲明,聲明這個控件必須使用賦予的權限,才可以顯示出界面。添加語句如下:

//設定控件的權限

[assembly: System.Security.AllowPartiallyTrustedCallers()]

     現在重新編譯,并且替換以前的dll,界面又可以顯示出來了。 

    到現在為止,我們編寫的還不是真正的ActiveX控件。這個控件隻是能夠實作自身的顯示,并且不能實作更多的功能,比如實作與腳本的互動或者操作用戶端的系統資料庫或者磁盤。這如果我們希望這個控件突破.Net Framework安全模型的限制,實作與腳本的互動或者操作用戶端的系統資料庫或者磁盤的話,必須要讓它成為真正的ActiveX控件。

二. 将使用者控件變成Com可見

    1.在HelloWorld(使用者控件)項目上點選右鍵,選擇屬性,将打開項目屬性面闆,選擇應用程式标簽頁,點選“程式集資訊”按鈕,在彈出的視窗中勾選“使程式集COM可見”(下圖為别人的圖檔,僅供參考)

    2.切換到生成标簽頁,然後勾選“為Com互操作注冊”,在該頁面的最上面,有一個配置選項,切換到realse,并再次勾選“為Com互操作注冊”。這樣無論是在debug還是在release狀态下,都可以把使用者控件當做com接口使用。如下圖。(如果不使用realse模式,realse可以不設定。) 

     注意:在Win7中,溝選“為Com互操作注冊”後,如果不是Administrtor使用者,編譯項目會出錯。是以一定要記得在Administrator下編寫代碼。 

3、修改使用者控件背景代碼,代碼如下, 

using System.Runtime.InteropServices;

namespace HelloWorld

{

    [Guid("F3F99F87-276D-4F7C-96F9-85F5261773CD")]

    public partial class Demo: UserControl

    {

        public Demo()

        {

            InitializeComponent();

        }      

    }  

}

     注:建立Guid的方法如下:

        在vs2010中,工具->建立GUID,在彈出的視窗中,在GUID格式中選擇第五個,點選建立GUID,然後點選複制,然後在點選退出,此時傳回到VS2010中,在相應位置粘貼即可。 

     重新編譯,使用VS2010編譯後,此控件會自動被注冊在系統中。我們隻需要在“OLE/COM對象檢視器”中點Grouped by Component Category->.Net Category->點選你編寫的類庫名.使用者控件類檢視。如下圖。“OLE/COM對象檢視器”位于開始菜單->Vs2010安裝目錄->Microsoft Windows SDK Tools中。

  可以看到,我們寫的HelloWorld.Demo已經被正确識别為COM元件。現在,我們已經可以像使用其它ActiveX控件一樣在網頁中顯示了。在HelloWorld.Demo點選滑鼠右鍵,如圖: 

   選擇Copy HTML  Tag to Clipboard,可以将代碼拷入剪貼闆。 

   現在,我們改寫helloworld.htm,html代碼如下: 

C#編寫ActiveX控件

body bgcolor='#223344'> 

C#編寫ActiveX控件

="helloworld" 

C#編寫ActiveX控件

   classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96"> 

C#編寫ActiveX控件

object> 

C#編寫ActiveX控件

body> 

C#編寫ActiveX控件

使用IE檢視,我們的控件又可以在網頁中顯示了。不過,這個時候它已經不再是以前的.net WinForm控件了,而是貨真價實的ActiveX控件了。 

    不過,編寫ActiveX控件的任務還沒有完成。我們還沒有實作腳本互動或者讀寫I/O,也沒有實作ActiveX控件的自動分發。

三. 實作與Js互動

     我們在Demo中加入ShowMessage方法: 

C#編寫ActiveX控件

public void ShowMessage(string msg) 

C#編寫ActiveX控件

        { 

C#編寫ActiveX控件

            if(msg != null) 

C#編寫ActiveX控件

            { 

C#編寫ActiveX控件

                MessageBox.Show(msg); 

C#編寫ActiveX控件

            } 

C#編寫ActiveX控件

        } 

C#編寫ActiveX控件

    我們重新編譯。在重新通路頁面之前,我們先來修改html代碼: 

C#編寫ActiveX控件
C#編寫ActiveX控件
C#編寫ActiveX控件

   classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96" 

C#編寫ActiveX控件

> 

C#編寫ActiveX控件
C#編寫ActiveX控件

br> 

C#編寫ActiveX控件

input type='button' onclick='helloworld.ShowMessage(“Hello World!”)' value='Click'> 

C#編寫ActiveX控件
C#編寫ActiveX控件

    現在,重新通路http://localhost/helloworld.htm,單擊Click按鈕,應該可以實作互動了。   

    但是結果卻很遺憾,我們發現IE跳出了對話框,(注,我在編寫此項目時,好像沒有跳出這個提示。)如圖所示: 

    單擊确定之後,我們發現JS報錯。根據提示,我們判斷可以通過修改IE的設定使控件運作。打開IE的 工具——〉Internet選項——〉安全——〉

本地Intranet——〉自定義級别——〉對沒有标記為安全的ActiveX控件進行初始化和運作,将其值設為啟用。我們重新整理頁面,現在終于可以正确運作了。

    當然,我們不能指望我們的客戶和我們一樣修改這個值。畢竟,一是操作麻煩,二是給電腦帶來了很大的安全風險。是以需要自義IObjectSafety接口,并讓UserControl實作接口。

    首先我們自己用C#定義這個接口,此接口必須與下邊接口代碼相同,包括Guid值都要一樣。

using System.Runtime.InteropServices;

    [Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    public interface IObjectSafety

        void GetInterfacceSafyOptions(

              System.Int32 riid,

              out System.Int32 pdwSupportedOptions,

              out System.Int32 pdwEnabledOptions);

        void SetInterfaceSafetyOptions(

             System.Int32 riid,

             System.Int32 dwOptionsSetMask,

             System.Int32 dwEnabledOptions);

    }

    public class CLsObjectSafety

        public const System.Int32 INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;

        public const System.Int32 INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;

     在UserControl背景實作接口,代碼如下。

    [Guid("F3F99F87-276D-4F7C-96F9-85F5261773CD")]

    public partial class Demo: UserControl,IObjectSafety

        }

        public void ShowMessage(string msg)

            if (msg != null)

            {

                MessageBox.Show(msg);

            }

        public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)

            // TODO:  添加WebCamControl.GetInterfacceSafyOptions 實作

            pdwSupportedOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_CALLER;

            pdwEnabledOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_DATA;

        public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)

            // TODO:  添加WebCamControl.SetInterfaceSafetyOptions 實作

     重新編譯,然後将IE裡面的設定改回來。現在,我們發現,和JS的互動已經沒有問題了。    

      這樣,一個最基本的ActiveX控件已經寫好了。你可以在這個控件的基礎上增加任何你需要的功能。到這裡,編寫控件的任務已經完成了。

四.打包并釋出ActiveX     ActiveX控件開發完成後,我們要将ActiveX控件打包和釋出,以便于使用者安裝。ActiveX控件可以使用VS 2010的安裝項目進行部署,使用VS 2010建立Windows Form的安裝工程就可以将ActiveX的dll進行打包。在打包時注意将ActiveX控件項目作為主輸出項目,并設定其Register屬性為vsdrpCOM,建立打包項目如下圖所示:       

    建立一個Windows 安裝項目,并給項目添加項目輸出,如下圖所示:

    在添加項目輸出時,我們将ActiveX項目添加進來,在項目中選擇ActiveX控件項目(CardReader.Controls),Primary Out(基本輸出),如下圖所示:

添加完檔案後,設定Primary Output From CardReader.Controls的Register屬性為vsdrpCOM。

設定完成後右擊安裝工程,修改安裝工程屬性,如下圖所示:

         在上圖中可以設定輸出的檔案名,這個檔案名就是打包後安裝檔案.MSI的檔案名。設定封包件、壓縮方式,CAB size,這三項均選擇預設值即可。

最後設定安裝URL,這裡的安裝URL是用來釋出或者使用ActiveX的URL位址的。(此處我沒弄明白這個位址到底有什麼用?)

     注:打包成exe檔案以後,我們可以進一步對安裝檔案進行打包成.cab檔案,安裝隐藏了msi 安裝界面,類似于cabarc 打包ocx 的效果

(點選install 之後其他的都背景做了),本文中暫不讨論,感興趣的讀者可以使用CAB SDK 中的工具CABARC.EXE (下載下傳位址 http://support.microsoft.com/kb/310618 )來進行。

這樣打封包件就生成了,将生成後的安裝檔案(exe和msi)拷貝到(本例中為預設網站目錄下的ActiveX檔案夾中),現在我們又要重新改動helloworld.htm檔案了。修改後的結果如下: 

object id="helloworld"

   classid="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96" codebase="Setup.exe"> 

object>

br>

input type='button' onclick='helloworld.ShowMessage("Hello World!")' value='Click'>

    注意,我們在object塊中加入了codebase屬性,這就是制定的下載下傳控件的位置,可以使用相對路徑。當使用codebase進行安裝時,Ie仍然會攔截,不允許安裝。需要将目前網站添加到信任站點中。如果這樣的話,可以直接給個連結讓使用者自已下載下傳安裝。對于這兩種方法需要待觀察。

    别忙,我們現在還不能正确請求這個頁面,因為我們還沒有對我們的控件進行簽名。

    簽名可以采用兩種方式,一種是在上面生成安裝程式的時候簽名,另一種是使用sn.exe簽名。推薦大家使用後者。

繼續閱讀