【问题标题】:How do I create an COM visible class in C#?如何在 C# 中创建 COM 可见类?
【发布时间】: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/…

标签: visual-studio-2010 c#-4.0 com


【解决方案1】:

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

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

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

输出将是:

我以发布脚本为生

【讨论】:

  • 另外,如果您构建了程序集并且在使用它时遇到问题:(“无法创建对象”错误)stackoverflow.com/questions/1208180/…stackoverflow.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】:

创建步骤

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

参考文献

【讨论】:

    【解决方案3】:

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

    确保程序集对 COM 可见:

    最后使用regasm.exe注册:

    regasm.exe /codebase mylib.dll
    

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

    【讨论】:

    • “声明一个类型,其方法将作为 COM 对象公开”?我是否必须明确实现一个接口并给它一个 GUID 或者“Make Assem.COM Visible”选项是否全部?
    • 这个我也不明白。您所说的“使用将公开为 COM 对象的方法声明类型”是什么意思?
    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 2013-02-04
    • 1970-01-01
    • 2021-08-30
    • 2019-02-02
    • 2016-01-24
    • 2011-06-17
    相关资源
    最近更新 更多