如何在C#中创build一个ActiveX控件(COM)?
我正在尝试创build一个ActiveX控件。 我使用Visual Studio 2010 (.NET 4)。 我需要创build一个COM对象(在C#中),不知道如何开始(使用什么types的项目等)
好的,我find了解决办法,我会写在这里为了共同的利益。
- 以pipe理员身份启动VS2010。
- 打开一个类库项目(exmaple – MyProject)。
- 添加一个新的界面到项目(见下面的例子)。
- 添加一个
using System.Runtime.InteropServices;
到文件 - 添加属性InterfaceType,Guid到接口。
- 您可以使用工具 – >生成GUID(选项4)来生成Guid。
- 添加一个实现接口的类。
- 添加属性ClassInterface,Guid,ProgId到接口。
ProgId约定是{namespace}。{class} - 在AssemblyInfo文件的项目中的属性文件夹下,将ComVisible设置为true。
- 在项目属性菜单中,在生成选项卡中标记“注册COM互操作”
- build立这个项目
现在你可以使用它的ProgID来使用你的COM对象。
例如:C#代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace Launcher { [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")] public interface ILauncher { void launch(); } [ClassInterface(ClassInterfaceType.None), Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYY"), ProgId("Launcher.Launcher")] public class Launcher : ILauncher { private string path = null; public void launch() { Console.WriteLine("I launch scripts for a living."); } } }
和使用COM的VB脚本:
set obj = createObject("PSLauncher.PSLauncher") obj.launch()
和输出将是:
我为了生计启动脚本
创build步骤
- 以pipe理员身份启动Visual Studio 2013
- 安装Visual Studio扩展Microsoft Visual Studio安装程序项目
- 创build一个类库项目(WinFormActivex)
- 创build您的示例窗口窗体(MainWindow)
- 创build一个新的组件接口(ILauncher)
- 创build一个新的安全接口(IObjectSafety)
- 创build实现接口的组件控件(Launcher)并启动窗口。
- 检查所有GUID是否由您生成
- 检查项目是否标记为COM
- 使用WinFormActivex的主输出创build安装项目(LauncherInstaller),其属性为
Register = vsdrpCOM
- 安装LauncherInstaller
- 在资源pipe理器(test.html)中运行你的testing页面
MainWindow你可以创build一个正常的Form,这里是预生成的。
public partial class MainWindow : Form { public MainWindow() { InitializeComponent(); } /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // textBox1 // this.textBox1.Location = new System.Drawing.Point(42, 23); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(100, 20); this.textBox1.TabIndex = 0; // // textBox2 // this.textBox2.Location = new System.Drawing.Point(42, 65); this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(100, 20); this.textBox2.TabIndex = 0; // // MainWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 261); this.Controls.Add(this.textBox2); this.Controls.Add(this.textBox1); this.Name = "MainWindow"; this.Text = "MainWindow"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.TextBox textBox2; }
ILauncher
using System.Runtime.InteropServices; namespace WinFormActivex { [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsDual)] [Guid("94D26775-05E0-4B9C-BC73-C06FE915CF89")] public interface ILauncher { void ShowWindow(); } }
IObjectSafety的
[ComImport()] [Guid("51105418-2E5C-4667-BFD6-50C71C5FD15C")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IObjectSafety { [PreserveSig()] int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions); [PreserveSig()] int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions); }
启动器请在这里生成您的GUID。
[ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] [Guid("D100C392-030A-411C-92B6-4DBE9AC7AA5A")] [ProgId("WinFormActivex.Launcher")] [ComDefaultInterface(typeof(ILauncher))] public class Launcher : UserControl, ILauncher, IObjectSafety { #region [ ILauncher ] public void ShowWindow() { var f = new MainWindow(); f.StartPosition = FormStartPosition.Manual; f.Location = Screen.AllScreens[0].Bounds.Location; f.WindowState = FormWindowState.Normal; f.WindowState = FormWindowState.Maximized; f.ShowInTaskbar = false; f.Show(); } #endregion #region [ IObjectSafety ] public enum ObjectSafetyOptions { INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001, INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002, INTERFACE_USES_DISPEX = 0x00000004, INTERFACE_USES_SECURITY_MANAGER = 0x00000008 }; public int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions) { ObjectSafetyOptions m_options = ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER | ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA; pdwSupportedOptions = (int)m_options; pdwEnabledOptions = (int)m_options; return 0; } public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) { return 0; } #endregion }
test.html请检查您的CLSID是否匹配(启动器)GUID。
<html> <head> <objectname="activexLauncher" style='display:none' id='activexLauncher' classid='CLSID:D100C392-030A-411C-92B6-4DBE9AC7AA5A' codebase='WinFormActivex'></object> <script language="javascript"> <!-- Load the ActiveX object --> var x = new ActiveXObject("WinFormActivex.Launcher"); alert(x.GetText()); </script> </head> <body> </body> </html>
参考
- 堆栈溢出问题我总是用作参考
- Activex标签你应该阅读
- 旧的微软指南
- 关于创build具有安全选项的acrivex控制的文章
- 关于创build窗口的文章
你可以使用一个类库项目。 使用将作为COM对象公开的方法声明一个types。
确保程序集已经成为可见的:
最后使用regasm.exe注册它:
regasm.exe /codebase mylib.dll
现在,该程序集将作为COM对象公开,并且您声明的types可以由任何支持COM的客户端使用。