精華:用C#編寫ActiveX控件

引用:http://www.cnblogs.com/homer/archive/2005/01/04/86473.html

 
用C#編寫ActiveX控件(一)

    前些日子做一個Web項目,必須自己編寫一個ActiveX控件。如今的ActiveX控件大多是使用VB/C++來開發的,而我對他們並不熟悉,因此考慮使用熟悉的C#編寫ActiveX控件。 

    首先,建立一個WinForm控件項目HelloWorld,並拖入一個Label控件,文字設爲HelloWorld,如圖: 

1.JPG

UserControl1.cs內容如下: 
None.gifusing System; 
None.gif
using System.Collections; 
None.gif
using System.ComponentModel; 
None.gif
using System.Drawing; 
None.gif
using System.Data; 
None.gif
using System.Windows.Forms; 
None.gif 
None.gif
namespace HelloWorld 
ExpandedBlockStart.gif

ExpandedSubBlockStart.gif    
/// <summary> 
InBlock.gif    
/// UserControl1 的摘要說明。 
ExpandedSubBlockEnd.gif    
/// </summary>
 
InBlock.gif    public class Demo : System.Windows.Forms.UserControl 
ExpandedSubBlockStart.gif    

InBlock.gif        
private System.Windows.Forms.Label label1; 
ExpandedSubBlockStart.gif        
/// <summary> 
InBlock.gif        
/// 必需的設計器變量。 
ExpandedSubBlockEnd.gif        
/// </summary>
 
InBlock.gif        private System.ComponentModel.Container components = null
InBlock.gif 
InBlock.gif        
public Demo() 
ExpandedSubBlockStart.gif        

InBlock.gif            
// 該調用是 Windows.Forms 窗體設計器所必需的。 
InBlock.gif
            InitializeComponent(); 
InBlock.gif 
InBlock.gif            
// TODO: 在 InitComponent 調用後添加任何初始化 
InBlock.gif
 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif 
ExpandedSubBlockStart.gif        
/// <summary> 
InBlock.gif        
/// 清理所有正在使用的資源。 
ExpandedSubBlockEnd.gif        
/// </summary>
 
InBlock.gif        protected override void Dispose( bool disposing ) 
ExpandedSubBlockStart.gif        

InBlock.gif            
if( disposing ) 
ExpandedSubBlockStart.gif            

InBlock.gif                
if( components != null ) 
InBlock.gif                    components.Dispose(); 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
base.Dispose( disposing ); 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif 
ContractedSubBlock.gif        
組件設計器生成的代碼 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
 
None.gif

    此時編譯項目,可以生成HelloWorld.dll。將此dll拷貝到IIS的虛擬根目錄下,然後建立一個helloworld.htm的文件,html代碼如下: 
None.gif<body bgcolor='#223344'> 
None.gif
<object id="helloworld" classid=’http://localhost/HelloWorld.dll#HelloWorld.Demo’ Width="184" Height="96" VIEWASTEXT> </object> 
None.gif
</body>
在IE地址欄中輸入以下地址:http://localhost/helloworld.htm,出現界面: 

2.JPG

如圖,控件已經成功在頁面上顯示了。OK,我們已經完成了第一步。 

    但是問題到這裏還沒有解決。不相信?你可以試試在另外一臺機器上測試,注意需要修改對應的html代碼和URL地址。你可以看到這個在原來顯示控件的地方是一個紅色的叉,或者還會彈出一個對話框,表示這個控件沒有任何權限。出現這個結果是微軟的默認設置造成的,作者必須在控件所在的控件的 AssemblyInfo.cs/vb 中執行一個安全聲明,聲明這個控件必須使用賦予的權限,纔可以顯示出界面。我們在AssemblyInfo.cs中引用System.Security命名空間,並添加一句: 
None.gif[assembly : AllowPartiallyTrustedCallers()]
現在重新編譯,並且替換以前的dll,界面又可以顯示出來了。 

    需要提醒的是,到現在爲止,我們編寫的還不是真正的ActiveX控件。這個控件到現在爲止,還只是能夠實現自身的顯示,並且不能實現更多的功能,比如實現與腳本的交互或者操作客戶端的註冊表或者磁盤。這是由於.Net Framework的安全模型所限制的。如果我們希望這個控件突破.Net Framework安全模型的限制,實現與腳本的交互或者操作客戶端的註冊表或者磁盤的話,必須要讓它成爲真正的ActiveX控件。下面,我們把剛纔的控件變成真正的ActiveX控件。 

    首先使用 工具—〉創建GUID 生成一個GUID,並修改UserControl1.cs文件。首先增加引用System.Runtime.InteropServices命名空間,並在Demo前面加入一條語句: 

3.JPG

注意Guid中的字符串,就是你生成的Guid字符串。它是你所生成的ActiveX控件的唯一標識符。然後修改項目屬性,如圖: 
4.JPG 
注意面板中的最後一項,我們唯一需要修改的是將其值改爲True。 

    重新編譯。我們使用 工具—〉OLE/COM對象查看器 查看,如圖: 
5.JPG 
可以看到,我們寫的HelloWorld.Demo已經被正確識別爲COM組件。現在,我們已經可以像使用其它ActiveX控件一樣在網頁中顯示了。在HelloWorld.Demo點擊鼠標右鍵,如圖: 
6.JPG 
選擇Copy HTML <object> Tag to Clipboard,可以將代碼拷入剪貼板。 

現在,我們改寫helloworld.htm,html代碼如下: 
None.gif<body bgcolor='#223344'> 
None.gif
<object id="helloworld" 
None.gif   classid
="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96"> 
None.gif
</object> 
None.gif
</body> 
None.gif
使用IE查看,我們的控件又可以在網頁中顯示了。不過,這個時候它已經不再是以前的.net WinForm控件了,而是貨真價實的ActiveX控件了。 

    不過,編寫ActiveX控件的任務還沒有完成。我們還沒有實現腳本互動或者讀寫I/O,也沒有實現ActiveX控件的自動分發。在下一篇Blog中,我會完成ActiveX控件的編寫。 

    PS:這是我在博客園上的第一個Post,希望得到大家的支持。

C#編寫ActiveX控件(二)

                            Homer

 

       在我的上一篇blog中,已經實現了一個最基本的ActiveX控件。當然,我們編寫的任務還沒有完成。首先,我們先嚐試實現和JS的交互能力。

 

       我們在Demo中加ShowMessage方法: 
None.gifpublic void ShowMessage(string msg) 
ExpandedBlockStart.gif        

InBlock.gif            
if(msg != null
ExpandedSubBlockStart.gif            

InBlock.gif                MessageBox.Show(msg); 
ExpandedSubBlockEnd.gif            }
 
ExpandedBlockEnd.gif        }
 
None.gif
我們重新編譯。在重新訪問頁面之前,我們先來修改html代碼: 
None.gif<body bgcolor='#223344'> 
None.gif
<object id="helloworld" 
None.gif   classid
="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96" 
None.gif
> 
None.gif
</object> 
None.gif
<br> 
None.gif
<input type='button' onclick='helloworld.ShowMessage(“Hello World!”)' value='Click'> 
None.gif
</body> 
None.gif

現在,重新訪問http://localhost/helloworld.htm,單擊Click按鈕,應該可以實現交互了。

 

    但是結果卻很遺憾,我們發現IE跳出了對話框,如圖所示: 

7.JPG 
單擊確定之後,我們發現JS報錯。根據提示,我們判斷可以通過修改IE的設置使控件運行。打開IE的 工具——〉Internet選項——〉安全——〉本地Intranet——〉自定義級別——〉對沒有標記爲安全的ActiveX控件進行初始化和運行,將其值設爲啓用。我們刷新頁面,現在終於可以正確運行了。

 

    當然,我們不能指望我們的客戶和我們一樣修改這個值。畢竟,一是操作麻煩,二是給電腦帶來了很大的安全風險。在互聯網上搜索之後,發現必須要實現IObjectSafety接口,把ActiveX控件標記爲安全的ActiveX控件。在搜索MSDN之後,我找到了IObjectSafety接口的定義。這就好辦了。首先我們自己用C#實現這個接口: 
None.gif[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
None.gif    
public interface IObjectSafety 
ExpandedBlockStart.gif    

InBlock.gif        
// methods 
InBlock.gif
        void GetInterfacceSafyOptions( 
InBlock.gif            System.Int32 riid, 
InBlock.gif            
out System.Int32 pdwSupportedOptions, 
InBlock.gif            
out System.Int32 pdwEnabledOptions); 
InBlock.gif        
void SetInterfaceSafetyOptions( 
InBlock.gif            System.Int32 riid, 
InBlock.gif            System.Int32 dwOptionsSetMask, 
InBlock.gif            System.Int32 dwEnabledOptions);         
ExpandedBlockEnd.gif    }
 
None.gif

注意,這個GUID是不能改的。然後,我們在Demo類裏面實現這個接口。增加一下代碼: 

ContractedBlock.gifIObjectSafety 成員 
None.gif

重新編譯,然後將IE裏面的設置改回來。現在,我們發現,和JS的交互已經沒有問題了。 

    這樣,一個最基本的ActiveX控件已經寫好了。你可以在這個控件的基礎上增加任何你需要的功能。到這裏,編寫控件的任務已經完成了,我們的下一個目標就是發佈它。

在前面我們已經完成了ActiveX控件的開發,接下來的就是發佈它了。 

        首先,我們建立一個windows安裝項目,並將ActiveX控件的主輸出添加到項目輸出中。然後,改動ActiveX控件的主輸出文件,將其Register屬性改爲vsdrpCOM.如圖: 

8.JPG

下一步,我們改動項目屬性,將引導程序更改爲 Web引導程序。很遺憾的是,在 Web引導程序設置 中的安裝文件夾URL中必須使用絕對路徑,不能使用相對路徑。這意味着生成安裝程序的時候就必須確定路徑,不是很方便。在示例中,我使用了localhost,在發佈中可以改爲實際的域名。

9.JPG

    現在我們生成安裝程序,並把相應得程序拷貝到正確的目錄中(本例中爲默認網站目錄下的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控件》完結。大家有什麼問題,可以和我留言。  

       NEW:源碼下載

紅馬天下 版權所有


    在我的第一篇blog發表之後,得到大家的支持,我的工作得到了認可,感到很開心。emteeth.gif當然,很多朋友也提出了很多出色的見地。我想在這裏說明一下我對這些問題的理解。  
   
    我所完成的控件是一個用來獲取客戶端攝像頭圖片並保存在特殊文件夾裏,然後上傳到服務器的ActiveX控件。給大家一個截圖。 顯示圖片的就是那個控件。 
1.JPG 

    之所以當初想到用C#寫ActiveX控件,一是自己不會用VB/C++寫ActiveX控件,二是由於簡單的WinForm控件由於.net安全性的限制,無法在客戶端實現複雜的操作。因爲ActiveX控件是以本地用戶的身份運行,所以可以突破.net安全性的限制。而這纔是《用C#編寫ActiveX控件》的真正優勢所在。 
     
    其實用C#寫ActiveX控件的原理很簡單,就是使用了.net平臺和COM的互操作性。在我的《用C#編寫ActiveX控件》中,修改項目屬性的目的就是將.net控件註冊爲ActiveX控件。這樣,你就可以把這個控件完全當作ActiveX控件來對待了。比如,可以使用JS和VBS來調用,也可以使用C++來調用。唯一的遺憾,就是這樣的ActiveX控件需要客戶端安裝.net framework。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章