簡體   English   中英

如何在 C# 中創建 ActiveX 控件?

[英]How to create an ActiveX control in C#?

我無法在 C# 中創建功能正常的 ActiveX 控件; 我曾嘗試按照教程這樣做但沒有成功。

我創建了一個示例類庫項目,其中包含以下代碼:

namespace AACWCSurvey
{
    [ProgId("Prisoner.PrisonerControl")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class Class1
    {
        public Class1()
        {
            MessageBox.Show("FIRETRUCK!!!");
        }
    }
}

然后我做了以下步驟:

  1. 屬性 => 應用程序 => 程序集信息 => 使程序集 COM 可見
  2. 構建 => 注冊 COM 互操作 TRUE(選中)
  3. 為程序集設置強名稱(簽名)
  4. 構建項目
  5. regasm MyDll.dll /tlb /codebase

  6. 在 tstcon32 中看不到Prisoner.PrisonerControl =(

我的操作系統是 WinXP x86。


UPD:它適用於 VBScript:

Dim objJava
Set objJava = WScript.CreateObject("Prisoner.PrisonerControl")

但它在 tstcon32 中不可見。

如果您使用 Prisoner.PrisonerControl 控件閱讀實際文章,則會在帶有您的控件 GUID 的鍵中創建一個名為Control的子鍵。

在我的機器上使用 guid {9DEA5F06-E324-31A7-837B-D0F3BDE91423}創建密鑰

HKEY_CLASSES_ROOT\CLSID\{9DEA5F06-E324-31A7-837B-D0F3BDE91423}\Control

使控件出現在tstcon32 無論有沒有它,ActiveX 都可用於 javascript

var x = new ActiveXControl("Prisoner.PrisonerControl");

實際上,我不得不在 javascript 執行和注冊表路徑上與 windows 進行斗爭才能在我的系統上對其進行測試,因為它是一台 x64 機器,但那是另一回事了。

您已經創建了一個 COM 服務器,但沒有創建一個 ActiveX 控件,它是一個復雜得多的 COM 對象,您可以使用 tstcon32.exe 練習這種對象。

它必須實現一堆接口,關鍵是IOleObject和IOleWindow。 允許它與 ActiveX 主機進行所需協商並創建可見窗口的接口類型。 Winforms Control 類是創建一個的最佳選擇。

以下是外部記錄的相關步驟。 這是總結,省略了一些說明,但沒有任何必要的步驟。

此示例也與 Garry Trinder 於 2008 年 11 月 25 日發表的文章將托管控件用作 ActiveX 控件非常相似,我也包含了本文中的一些注釋。

將 Windows 窗體控件公開為 ActiveX 控件

本文將介紹如何在 .NET 之外使用 Windows 窗體控件。

編寫控件

  1. 從 Visual Studio 中創建一個新的控件項目 - 我的示例都是用 C# 編寫的,但也可以使用 VB.NET。

[此處 Garry 的文章建議,“首先,創建一個托管用戶控件項目——Windows 窗體類庫或控件庫項目。使用用戶控件設計器以您想要的方式設計您的自定義用戶控件(使用您喜歡的任何標准控件)。 ” ]

  1. 將控件等添加到表單中,放入代碼等。

  2. 添加以下 using 子句...

 using System.Runtime.InteropServices; using System.Text; using System.Reflection; using Microsoft.Win32;
  1. 屬性您的類,以便它獲得 ProgID。 這不是絕對必要的,因為會生成一個,但最好是明確的。

 [ProgId("Prisoner.PrisonerControl")] [ClassInterface(ClassInterfaceType.AutoDual)]

這會分配 ProgID,並定義公開的接口應該是“AutoDual”——這為您從類的所有公共非靜態成員中生成了一個默認接口。 如果這不是您想要的,請使用其他選項之一。

  1. 更新項目屬性,以便為 COM 互操作注冊程序集。

如果您使用的是 VB.NET,您還需要一個強命名程序集。 奇怪的是,在 C# 中你沒有 - 它似乎是環境的一個特性,而不是編譯器或 CLR 的一個特性。

  1. 將以下兩個方法添加到您的類中。

 [ComRegisterFunction()] public static void RegisterClass ( string key ) { // Strip off HKEY_CLASSES_ROOT\\ from the passed key as I don't need it StringBuilder sb = new StringBuilder ( key ) ; sb.Replace(@"HKEY_CLASSES_ROOT\\","") ; // Open the CLSID\\{guid} key for write access RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true); // And create the 'Control' key - this allows it to show up in // the ActiveX control container RegistryKey ctrl = k.CreateSubKey ( "Control" ) ; ctrl.Close ( ) ; // Next create the CodeBase entry - needed if not string named and GACced. RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ; inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ; inprocServer32.Close ( ) ; // Finally close the main key k.Close ( ) ; }

RegisterClass 函數具有 ComRegisterFunction 的屬性 - 當為 COM Interop 注冊程序集時,將調用此靜態方法。 我在這里所做的就是將“Control”關鍵字添加到注冊表,並添加到 CodeBase 條目中。

CodeBase 很有趣 - 不僅適用於 .NET 控件。 它定義了一個可以找到代碼的 URL 路徑,它可以是磁盤上的程序集,如本例中那樣,也可以是 Web 服務器上某處的遠程程序集。 當運行時嘗試創建控件時,它將探測此 URL 並根據需要下載控件。 這在測試 .NET 組件時非常有用,因為與 .EXE 駐留在同一目錄(等)中的通常警告不適用。

 [ComUnregisterFunction()] public static void UnregisterClass ( string key ) { StringBuilder sb = new StringBuilder ( key ) ; sb.Replace(@"HKEY_CLASSES_ROOT\\","") ; // Open HKCR\\CLSID\\{guid} for write access RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true); // Delete the 'Control' key, but don't throw an exception if it does not exist k.DeleteSubKey ( "Control" , false ) ; // Next open up InprocServer32 RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ; // And delete the CodeBase key, again not throwing if missing k.DeleteSubKey ( "CodeBase" , false ) ; // Finally close the main key k.Close ( ) ; }

第二個函數將刪除(如果)類未注冊時添加的注冊表項 - 隨時整理總是一個好建議。

現在您已准備好編譯和測試您的控件。

Garry 博客的其他說明:

[The] 附加注冊表項: ControlMiscStatusTypeLibVersion [可以創建] 使用.REG腳本,但通常最好編寫將在注冊/注銷時調用的函數

他詳細描述了注冊表項:

Control是一個空子項。 TypeLib映射到TypeLib的 GUID(這是 assemblyinfo.cs 中的程序集級 GUID)。 Version是來自程序集版本的主要和次要版本號。 唯一稍微有趣的子項是MiscStatus 這需要設置為由OLEMISC枚舉中的(按位)值組成的值, 記錄在此處 要使此枚舉可用,請添加對Microsoft.VisualStudio.OLE.Interop的引用(以及適合命名空間的“using”語句)。

他的最后一句話是警告:

注意:這似乎適用於 Excel(我所做的測試非常有限),部分適用於 PowerPoint,但在 Word 中失敗。 可能,更多的OLEMISC值可能會改善這一點; 可能有一些消息我們需要掛鈎; 可能還有一些我們需要實現的接口......事實上,我只是勉強讓它以非常有限的方式工作,這應該告訴你,這可能不是你想要以任何嚴肅的方式使用的技術。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM