利用雙休的時間研究了一下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代碼如下:

body bgcolor='#223344'>

="helloworld"

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

object>

body>

使用IE檢視,我們的控件又可以在網頁中顯示了。不過,這個時候它已經不再是以前的.net WinForm控件了,而是貨真價實的ActiveX控件了。
不過,編寫ActiveX控件的任務還沒有完成。我們還沒有實作腳本互動或者讀寫I/O,也沒有實作ActiveX控件的自動分發。
三. 實作與Js互動
我們在Demo中加入ShowMessage方法:

public void ShowMessage(string msg)
{
if(msg != null)
{
MessageBox.Show(msg);
}
}

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



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

>


br>

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


現在,重新通路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簽名。推薦大家使用後者。