承接《C# 開發 ActiveX 控制項(一):建立基礎控制項》,本文將實作兩項關鍵功能:暴露方法給 JavaScript 呼叫,以及實作 IObjectSafety 介面將控制項標記為安全,解決 IE 預設阻擋未標記安全控制項的問題。
在控制項類別(繼承 UserControl)中直接定義 public 方法,即可被網頁腳本存取:
public void ShowMessage(string msg)
{
if (!string.IsNullOrEmpty(msg))
{
MessageBox.Show(msg); // 示範用,實務建議用自訂 UI
}
}
<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'>
初次載入時,IE 會彈出警告:「這個控制項未標記為安全,無法初始化」。使用者若在「網際網路選項」→「安全性」→「自訂層級」啟用「對未標記為安全的 ActiveX 控制項初始化並執行」,雖可暫時繞過,但不可要求所有使用者手動調整。正解是實作 IObjectSafety 介面,讓控制項主動宣告安全。
using System;
using System.Runtime.InteropServices;
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
void GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
void SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
}
注意:GUID CB5BDC81-93C1-11CF-8F20-00805F2CD064 為標準常數,不可更改。
public class Demo : UserControl, IObjectSafety
{
// ... 既有程式碼 ...
#region IObjectSafety 成員
public void GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
{
// 支援 INTERFACESAFE_FOR_UNTRUSTED_CALLER (0x00000001) 與 INTERFACESAFE_FOR_UNTRUSTED_DATA (0x00000002)
pdwSupportedOptions = 1 | 2; // = 3
pdwEnabledOptions = 1 | 2; // 同時啟用兩者
}
public void SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
// 無需額外邏輯,IE 呼叫此方法即視為控制項同意安全標記
}
#endregion
}
ShowMessage,應無警告彈出且正常執行。| 常數 | 值 | 含義 |
|---|---|---|
| INTERFACESAFE_FOR_UNTRUSTED_CALLER | 0x00000001 | 允許不受信任的呼叫端(如網頁腳本)存取介面 |
| INTERFACESAFE_FOR_UNTRUSTED_DATA | 0x00000002 | 允許介面處理不受信任的資料 |
同時啟用兩者(值為 3)是通用做法,表示該控制項在腳本與資料層面皆安全。
透過實作 IObjectSafety 並回報支援 INTERFACESAFE_FOR_UNTRUSTED_CALLER 與 INTERFACESAFE_FOR_UNTRUSTED_DATA,C# ActiveX 控制項即可通過 IE 的安全檢查,無需使用者手動降低安全性設定。這是發布供公開網頁使用的 ActiveX 控制項的必要步驟。