web-dev-qa-db-fra.com

Comment créer une classe visible COM en C #?

J'utilise Visual Studio 201 (.NET 4). J'ai besoin de créer un objet COM (en C #) et je n'ai aucune idée de comment commencer (quel type de projet utiliser, etc.)

48
Eyal

OK j'ai trouvé la solution et je vais l'écrire ici pour le bien commun.

  1. Démarrez VS2010 en tant qu'administrateur.
  2. Ouvrez un projet de bibliothèque de classes (exmaple - MyProject).
  3. Ajoutez une nouvelle interface au projet (voir l'exemple ci-dessous).
  4. Ajoutez un using System.Runtime.InteropServices; Au fichier
  5. Ajoutez les attributs InterfaceType, Guid à l'interface.
  6. Vous pouvez générer un Guid en utilisant Tools-> Generate GUID (option 4).
  7. Ajoutez une classe qui implémente l'interface.
  8. Ajoutez les attributs ClassInterface, Guid, ProgId à l'interface.
    La convention ProgId est {namespace}. {Class}
  9. Sous le dossier Propriétés du projet dans le fichier AssemblyInfo, définissez ComVisible sur true.
  10. Dans le menu des propriétés du projet, dans l'onglet de génération, marquez "Register for COM interop"
  11. Construire le projet

vous pouvez maintenant utiliser votre objet COM en utilisant son ProgID.

exemple: le code 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.");

        }

    }
}

et VB utilisant le COM:

set obj = createObject("PSLauncher.PSLauncher") obj.launch()

et la sortie sera:

Je lance des scripts pour vivre

70
Eyal

Étapes de création

  1. Démarrez Visual Studio 2013 en tant qu'administrateur
  2. Installer l'extension Visual Studio Projets d'installation de Microsoft Visual Studio
  3. Créer un projet de bibliothèque de classes (WinFormActivex)
  4. Créez votre exemple de formulaire de fenêtre (MainWindow)
  5. Créer une nouvelle interface de composant (ILauncher)
  6. Créer une nouvelle interface de sécurité (IObjectSafety)
  7. Créez le contrôle de composant (lanceur) qui implémente les interfaces et lancez la fenêtre.
  8. Vérifiez que tous les GUID sont générés par vous
  9. Vérifiez que le projet est marqué pour COM
  10. Créez le projet d'installation (LauncherInstaller) avec la sortie principale de WinFormActivex avec la propriété Register = vsdrpCOM
  11. Installer LauncherInstaller
  12. Exécutez votre page de test dans l'Explorateur (test.html)

MainWindow Vous pouvez créer un formulaire normal, voici pré-généré.

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);
    }

Lanceur Veuillez générer votre GUID ici.

 [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 Veuillez vérifier que votre GUID CLSID correspond à (Lanceur).

<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>

Références

16
Giulio Caccin

Vous pouvez utiliser un projet de bibliothèque de classes. Déclarez un type avec des méthodes qui seront exposées en tant qu'objet COM.

Assurez-vous que l'assemblage a été rendu COM-visible:

alt text

Et enfin l'enregistrer en utilisant regasm.exe :

regasm.exe /codebase mylib.dll

À présent, l'assembly est exposé en tant qu'objet COM et le type que vous avez déclaré peut être utilisé par tout client qui prend en charge COM.

13
Darin Dimitrov