如何在 C# 中创建 COM 可见类?

Posted

技术标签:

【中文标题】如何在 C# 中创建 COM 可见类?【英文标题】:How do I create an COM visible class in C#? 【发布时间】:2011-03-22 13:40:24 【问题描述】:

我使用Visual Studio 2010 (.NET 4)。我需要创建一个COM 对象(在 C# 中)并且不知道如何开始(使用什么类型的项目等)

【问题讨论】:

如果有人知道如何在 C# 中创建 COM 来帮助我入门,则不必是 ActiveX @Bujutsu 然而,ActiveX 部分将更难找到相关信息:简单的 WinForms 已得到广泛展示。 @Richard 我的答案的独特之处在于,我已经为 Windows 表单安全 Activex 提供了明确而全面的完整解决方案。另一个不太容易的区别是链接答案的不同 IDE,它适用于 Visual Studio 2010。感谢您的评论。 好吧,如果有人需要帮助,这个链接是一个很好的开始:blogs.msdn.microsoft.com/asiatech/2011/12/05/… 【参考方案1】:

好的,我找到了解决方案,为了共同利益,我会写在这里。

    以管理员身份启动 VS2010。 打开一个类库项目(例如 - MyProject)。 为项目添加一个新接口(参见下面的示例)。 将using System.Runtime.InteropServices; 添加到文件中 将属性 InterfaceType、Guid 添加到接口。 您可以使用工具->生成 GUID(选项 4)生成 Guid。 添加一个实现接口的类。 将属性 ClassInterface、Guid、ProgId 添加到接口。 ProgId 约定是 namespace.class 在AssemblyInfo 文件中项目的Properties 文件夹下,将ComVisible 设置为true。 在项目属性菜单中,在构建选项卡中标记“注册 COM 互操作” 构建项目

现在您可以通过使用它的 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()

输出将是:

我以发布脚本为生

【讨论】:

另外,如果您构建了程序集并且在使用它时遇到问题:(“无法创建对象”错误)***.com/questions/1208180/…***.com/questions/1281052/… 我按照上面的步骤,我的宏如下 Sub test() Dim ob As Object Set ob = CreateObject("ClassCom.Name") Dim name As String name = ob.launc() End Sub 它说“错误 429”activex 无法创建对象可能出了什么问题? 我遵循了同样的方法,但没有运气。当我使用 VB.Net 在远程机器上启动 exe 时,出现相同的错误 Activex 无法创建 示例 VB.Net 代码:Protected Sub Unnamed1_Click(sender As Object, e As EventArgs) Dim strRemoteServer = "xxxxx" Dim strUser = "xxx" Dim strPassword = "yyy" Dim strCommand strCommand = ""暗淡 objWMIService = GetObject("winmgmts:" & "impersonationlevel=impersonate!\\" & strRemoteServer & "\root\cimv2") 暗淡 objProcess = objWMIService.Get("Win32_Process") 暗淡 objQWCreate = objProcess.Create(strCommand) End Sub 错误:“无法创建 ActiveX 组件。”【参考方案2】:

创建步骤

    以管理员身份启动 Visual Studio 2013 安装 Visual Studio 扩展Microsoft Visual Studio Installer Projects 创建类库项目 (WinFormActivex) 创建示例窗口窗体 (MainWindow) 创建一个新的组件接口(ILauncher) 创建新的安全接口 (IObjectSafety) 创建实现接口并启动窗口的组件控件(启动器)。 检查所有 GUID 是否由您生成 检查项目是否标记为 COM 使用属性Register = vsdrpCOM 的 WinFormActivex 的主要输出创建安装项目 (LauncherInstaller) 安装 LauncherInstaller 在资源管理器中运行您的测试页面 (test.html)

主窗口 您可以创建一个普通的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>

参考文献

Stack Overflow question I always use as reference Activex tag you should read Old Microsoft guide Article on creating the acrivex control with security options Article about creating the window

【讨论】:

【参考方案3】:

您可以使用类库项目。使用将作为 COM 对象公开的方法声明一个类型。

确保程序集对 COM 可见:

最后使用regasm.exe注册:

regasm.exe /codebase mylib.dll

现在程序集作为 COM 对象公开,您声明的类型可以被任何支持 COM 的客户端使用。

【讨论】:

“声明一个类型,其方法将作为 COM 对象公开”?我是否必须明确实现一个接口并给它一个 GUID 或者“Make Assem.COM Visible”选项是否全部? 这个我也不明白。您所说的“使用将公开为 COM 对象的方法声明类型”是什么意思?

以上是关于如何在 C# 中创建 COM 可见类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在c#中创建指针类型类的指针

如何在 C# 中创建别名

如何在 C# 中创建音频频谱

如何在 C# 中创建基本的 IFC 文件

如何在 C# 中创建自定义属性

如何在 uwp C# 中创建手电筒应用程序