首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Visual C# 創建 COM 可見組件:從 Windows Forms 控件到 Web 頁面調用

     編輯:關於C語言

前言:C# 與 ActiveX 的本質關係

C# 編譯產出的是托管代碼,而傳統 ActiveX 組件是非托管代碼。兩者本質不同:.NET 追求「Write Once, Run Anywhere」跨平台,ActiveX 綁定 Windows 平台。VS.NET 提供的「引用 ActiveX」實際是通過互操作 (Interop) 生成運行時可調用包裝器 (RCW),將非托管 COM 組件包裝為托管類庫。同理,C# 創建的組件若需在 Web 頁面以 `` 標簽調用,必須將其接口以 COM 可見 方式發布,本質上仍是托管代碼,只是通過 COM Callable Wrapper (CCW) 暴露給非托管調用者。

開發環境

  • Windows 2000 Server
  • Visual Studio .NET 2003 Enterprise / .NET Framework SDK 1.1

第一部分:創建 Windows Forms 控件庫

步驟 1-6:新建類庫項目

  1. 菜單「文件」→「新建」→「項目」
  2. 項目類型:「Visual C# 項目」,模板:「類庫」
  3. 名稱:`ActiveXDotNet`,位置:`C:\Class`
  4. 刪除默認 `Class1.cs`
  5. 「項目」→「添加組件」→「組件類」,名稱:`MyControl.cs`

步驟 7-10:設計控件界面

在 `MyControl.cs [設計]` 視圖中,從工具箱拖入:

  • 一個 `GroupBox` (Text="Visual C# 創建的 COM 組件")
  • GroupBox 內放入 `Label` (Text="輸入信息:") 和 `TextBox` (Name=`txtUserText`, Enabled=False)

切換到代碼視圖,替換 `InitializeComponent` 為設計器生成的精確佈局代碼 (見原文),確保控件位置、大小正確。

步驟 11-12:定義 COM 可見接口與屬性

// 1. 定義 COM 可見接口 (供外部調用)
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)] // 雙重接口:支持早綁/晚綁
public interface IAxMyControl
{
    string UserText { get; set; }
}

// 2. 控件類實現接口,標記 COM 可見
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)] // 不自動生成類接口,僅暴露顯式接口
[ProgId("ActiveXDotNet.MyControl")] // 指定 ProgID,供 Web 頁面 classid 使用
public class MyControl : UserControl, IAxMyControl
{
    private string _userText = "";

    // 實現接口屬性
    public string UserText
    {
        get => _userText;
        set
        {
            _userText = value;
            // 同步更新 UI
            if (txtUserText != null) txtUserText.Text = value;
        }
    }

    // 構造函數、Dispose、InitializeComponent 等保持不變...
}

關鍵屬性解析

屬性作用
`[ComVisible(true)]`使類型對 COM 可見 (默認程序集 ComVisible=false 需在 AssemblyInfo.cs 開啟)
`[InterfaceType(ComInterfaceType.InterfaceIsDual)]`生成雙重接口 (vtable + IDispatch),支持 VB Script/JavaScript 晚綁調用
`[ClassInterface(ClassInterfaceType.None)]`禁止自動生成 `_MyControl` 類接口,強制通過 `IAxMyControl` 訪問,版本控制更安全
`[ProgId("...")]`指定友好程序標識符,Web 頁面 `

步驟 13-14:編譯與註冊

  1. 編譯生成 `ActiveXDotNet.dll` (輸出目錄 `bin\Debug`)
  2. 關鍵步驟:必須向系統註冊組件供 COM 調用:
    • 管理員命令行:regasm ActiveXDotNet.dll /tlb /codebase
    • 或項目屬性 → Build → 勾選「Register for COM interop」 (需 VS 管理員權限運行)

第二部分:Web 頁面測試調用

創建 test.htm

<html>
<body>
<hr>
<object id="MyControl1" 
        classid="clsid:YOUR_GUID_HERE" 
        width="288" height="72">
</object>
<!-- 或使用 ProgID: classid="ActiveXDotNet.MyControl" -->

<form name="frm">
<input type="text" name="txt" value="請輸入數據:">
<input type="button" value="確定" onclick="DOScript()">
</form>
<hr>

<script language="JavaScript">
function DOScript() {
    // JavaScript 調用 COM 組件屬性
    MyControl1.UserText = frm.txt.value;
}
</script>
</body>
</html>

部署與運行

  1. 將 `test.htm` 和 `ActiveXDotNet.dll` 複製到 IIS 虛擬目錄 (如 `C:\Inetpub\wwwroot`)
  2. 確保客戶端機器安裝 .NET Framework (運行托管代碼必需)
  3. IE 中訪問 `https://localhost/test.htm`
  4. 輸入文本點擊「確定」,觀察控件中 TextBox 顯示更新

核心原理深度解析

CCW (COM Callable Wrapper) 機制

  • 托管對象暴露給 COM 時,CLR 創建 CCW 作為代理
  • CCW 實現 `IUnknown`、`IDispatch` 等標準 COM 接口
  • COM 客戶端 (IE/JS) 調用 CCW,CCW 內部轉調托管對象方法
  • 引用計數由 CLR 管理,GC 回收時釋放 CCW

為什麼不是真正的 ActiveX?

  1. 本質是托管代碼:運行在 CLR 中,需 .NET Framework
  2. 無需下載安裝:Web 頁面不會下載 DLL 到客戶端 (除非 ClickOnce/IE 特定機制),服務端部署即可
  3. 安全性:受 CAS (代碼訪問安全) 管控,不需降低 IE 安全級別
  4. 跨平台潛力:若未來 Mono/其他 CLR 實現 CCW,理論可跨平台

部署最佳實踐

  • 服務端部署:DLL 放在網站 `bin` 目錄或 GAC,配置 IIS 應用程序池加載 .NET 版本
  • 客戶端前提:必須安裝對應版本 .NET Framework
  • 代碼簽名:強命名簽名 + Authenticode 簽名,提升信任度
  • XBAP / ClickOnce:現代替代方案,沙箱運行、自動更新、無需 COM 註冊

總結

本文演示了 C# 創建 COM 可見 Windows Forms 控件的完整流程:定義接口 → 實現控件 → 添加 COM 互操作屬性 → 編譯 → `regasm` 註冊 → Web 頁面 `` 標簽調用。關鍵在於理解托管組件通過 CCW 暴露給非托管環境的機制,而非生成傳統非托管 ActiveX DLL。現代 Web 開發推薦使用 JavaScript 框架 + Web API / SignalR 替代 COM 組件交互,但在舊系統遷移、特定 IE 專用場景下,此技術仍具備價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved