程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 使用C#實現ActiveX控件開發

使用C#實現ActiveX控件開發

編輯:關於C#

要使用C#實現一個ActiveX控件,需要解決三個問題:

1.使.NET組件能夠被COM調用

2.在客戶機上注冊後,ActiveX控件能通過IE的安全認證

3.未在客戶機上注冊時,安裝包能通過IE的簽名認證

本程序的開發環境是.NET Framework 3.5,工具是Visual Studio .NET 2008,在安裝.NET Framework 3.5的客戶機上通過測試。

下面是實現步驟:

(一)創建可從COM訪問的程序集

首先實現一個對COM可見的程序集,創建類庫工程,AssemblyInfo.cs應包含:

using System.Runtime.InteropServices;
//使此程序集中的類型對COM組件可見
[assembly: ComVisible(true)]
// 如果此項目向 COM 公開,則下列 GUID 用於類型庫的 ID
[assembly: Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]

加入以下代 碼到AssemblyInfo.cs確保程序集的可訪問性:

using System.Security;
[assembly: AllowPartiallyTrustedCallers()]

注意上面的Guid,如果程序集內部的類 未標注Guid,COM注冊的Guid是會新生成的,此處的Guid沒有作用。

創建用戶控件(自定義類待測)IdentityKey.cs,加入:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl
{
}
}

這裡的Guid和AssemblyInfo.cs一樣,它會在COM注冊中成為CLSID並被html以clsid調用 。

類庫工程屬性中,選擇生成,勾選COM注冊,在html文件中加入

<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357 -234D56D8F15E}" ></object>

在IE中啟用不安全控件,查看html頁面,應能訪問到控件,現在一個在發布時對COM注冊的程序集開發 完成了。

使用OLE/COM Object Viewer(安裝VC自帶)可以在.NET Categories中查看組件和CLSID。

(二)通過IE安全控件認證

如果客戶機的IE未開啟訪問非安全標記的ActiveX控件,通過IE浏覽上面的步驟開發出的ActiveX控件 ,發現IE會給出警告:

此頁上的 ActiveX 對象可能不安全的。 要允許它將初始化並通過腳本訪問嗎?

或禁止訪問。這是客戶機IE的安全規則設置的,我們應該在控件開發上解決IE安全認證的問題。首先 我們要了解IE是如何判斷一個ActiveX控件是不安全的,參見Microsoft幫助和支持文檔:

How Internet Explorer Determines If ActiveX Controls Are Safe

There are two ways to mark a control as safe for scripting and initialization:

1.Implement the IObjectSafety interface. 

2.Provide the following registry keys for the control's CLSID under the Implemented Categories section:

a.The following key marks the control safe for scripting:

{7DD95801-9882-11CF-9FA9-00AA006C42C4}

b.The following key marks the control safe for initialization from persistent data:

{7DD95802-9882-11CF-9FA9-00AA006C42C4} 

Microsoft recommends that you implement IObjectSafety to mark a control as safe or unsafe. This prevents other users from repackaging your control and marking it as safe when it is not.

我決定實現IObjectSafety接口來向IE表明ActiveX控件的安全標識,以保證控件再次打包時安全標識 不會被被改寫。

IObjectSafety是一個COM下的接口,對於C++程序來說,只需要實現它就行了,而.NET之下沒有這個接 口,在這種情況下,我們的ActiveX控件就是一個不帶類型庫的COM組件,必須使用C#代碼重新定義COM接 口。

這裡需要了解一點COM的接口知識。接口是COM的核心,它區分了在客戶和對象之間使用的契約和實現 。COM的接口有三種類型:定制接口÷分派接口和雙重接口。.NET Framework使用ComInterfaceType對它 進行了重定義:

namespace System.Runtime.InteropServices
{
// 摘要:
// Identifies how to expose an interface to COM.
[Serializable]
[ComVisible(true)]
public enum ComInterfaceType
{
// 摘要:
// Indicates the interface is exposed to COM as a dual interface, which enables
// both early and late binding. System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual
// is the default value.
InterfaceIsDual = 0,
//
// 摘要:
// Indicates an interface is exposed to COM as an IUnknown -derived interface,
// which enables only early binding.
InterfaceIsIUnknown = 1,
//
// 摘要:
// Indicates an interface is exposed to COM as a dispinterface, which enables
// late binding only.
InterfaceIsIDispatch = 2,
}
}

關於三個接口的具體描述,可以參考《C#高級編程第三版》28.1.3 接口。

在MSDN上查找,可以知道IObjectSafety繼承自IUnknown,是一個定制接口;通過上一章節,可以發現 向COM注冊時,需要提供一個Guid作為CLSID來標識程序集中的C#類,事實上在COM中,接口和類型庫都是 帶有Guid作為唯一標識的,分別為IID和typelib id。

這樣,通過在C#編寫的接口標上需要的COM接口IID,就可以在注冊是向COM表明接口身份了。在 Microsoft幫助上查找IObjectSafety定義:

[
uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
helpstring("VB IObjectSafety Interface"),
version(1.0)
]
library IObjectSafetyTLB
{
importlib("stdole2.tlb");
[
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
helpstring("IObjectSafety Interface"),
odl
]
interface IObjectSafety:IUnknown {
[helpstring("GetInterfaceSafetyOptions")]
HRESULT GetInterfaceSafetyOptions(
[in] long riid,
[in] long *pdwSupportedOptions,
[in] long *pdwEnabledOptions);
[helpstring("SetInterfaceSafetyOptions")]
HRESULT SetInterfaceSafetyOptions(
[in] long riid,
[in] long dwOptionsSetMask,
[in] long dwEnabledOptions);
}
}

其中的uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064)就是需要的接口IID。

使用C#編寫IObjectSafety:

using System;
using System.Runtime.InteropServices;
namespace KeyActiveX
{
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
void GetInterfacceSafyOptions(
int riid,
out int pdwSupportedOptions,
out int pdwEnabledOptions);
[PreserveSig]
void SetInterfaceSafetyOptions(
int riid,
int dwOptionsSetMask,
int dwEnabledOptions);
}
}

InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因為 IObjectSafety繼承自IUnkown。

接下來是KeyActiveX的接口實現:

namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl, IObjectSafety
{
#region IObjectSafety 成員
public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}
public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
{
throw new NotImplementedException();
}
#endregion
}
}

通過返回一個已定值來告訴IE控件是安全的。具體參見

如何在 VisualBasic 控件實現 IObjectSafety

(三)簽名發布

C#開發的ActiveX控件發布方式有三種:

制作客戶端安裝包,分發給客戶機安裝;

制作在線安裝包,客戶機聯機安裝;

使用html中object的codebase指向安裝包地址。

前兩個比較簡單,適合在局域網內實施,生成安裝包時需要裝Register屬性設置為vsdrpCOM;最後一 種方式,需要在安裝包上進行數字簽名,以保證客戶機的安全信任。受信任的簽名證書應該向證書提供商 (如Versign)購買,然後使用簽名工具對安裝包進行簽名。

下面利用Visual Studio 2008自帶的測試證書創建工具MakeCert和簽名工具SignTool進行測試,首先 創建一個帶有公司信息的測試證書,在Visual Studio命令提示符後輸入:

makecert -sk ABC -n "CN=ABC Corporation" f:\abccorptest.cer

在F盤上創建了測試證書。然後輸入

signtool signwizard

在Signing Options頁面上,選擇Custom,定義證書文件的位置,再下一步選擇一個加密算法(MD5或 SHA1),指定應用程序的名稱和描述URL,確認。

此時ActiveX控件安裝包有了一個被標記為未信任的測試證書,需要將IE設置為啟用未信任安裝程序, 在html中引用

<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357 -234D56D8F15E}" codebase="setup.exe" ></object>

客戶機安裝之後就可以使用ActiveX控件了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved