Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution
Consommez des composants COM depuis C# avec RCW, importez des bibliothèques de types et gérez les exceptions HRESULT.
Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.
Qu'est-ce que l'interopérabilité COM ?
COM (modèle d'objets composants) est l'ancien standard d'interface binaire de Microsoft, encore utilisé par Office, Windows Shell, les anciennes API DirectX et de nombreux outils d'entreprise. .NET peut utiliser des composants COM via des wrappers d'interopérabilité qui assurent la conversion entre les objets managés et les interfaces COM.
Enveloppes appelables à l'exécution (RCW)
Lorsque vous accédez à un objet COM depuis .NET, le CLR crée une enveloppe appelable à l'exécution (RCW), c'est-à-dire un proxy managé qui encapsule l'objet COM. La RCW gère automatiquement le comptage des références (AddRef/Release), le modèle d'appartements des threads et la conversion entre les types COM et .NET.
// The RCW is created automatically when you instantiate a COM class
// via a registered ProgID or CLSID
// Example: create an Excel Application COM object
Type excelType = Type.GetTypeFromProgID("Excel.Application")!;
object excelApp = Activator.CreateInstance(excelType)!;
// excelApp is an RCW — the CLR wraps the underlying IDispatch COM object
// COM AddRef is called; CLR tracks references
Console.WriteLine(excelApp.GetType().Name); // ApplicationClassImporter des bibliothèques de types (TLB)
L'outil tlbimp.exe (importateur de bibliothèques de types) lit une bibliothèque de types COM (.tlb ou intégrée dans .dll) et génère un assembly .NET d'interopérabilité contenant des classes RCW et des définitions d'interfaces fortement typées.
// From a Developer Command Prompt:
// tlbimp MyComLib.dll /out:MyComLib.Interop.dll
// Or reference via Visual Studio:
// Add Reference → COM → Microsoft Excel 16.0 Object Library
// → Generates Microsoft.Office.Interop.Excel.dll automatically
// The generated Interop assembly contains:
// - Interface types (matching COM vtable layout)
// - Co-class wrappers (implement the interfaces)
// - Enum types (from the type library)
// - Delegate types for COM event sinksUtiliser un objet COM via un assembly d'interopérabilité
Une fois l'assembly d'interopérabilité référencé, les types COM ressemblent à des types .NET ordinaires. L'appel d'une méthode est traduit par la RCW en une distribution via une table virtuelle COM. Libérez toujours correctement les objets COM pour éviter les fuites de ressources.
using Microsoft.Office.Interop.Excel;
Application excel = new Application();
excel.Visible = false;
Workbooks books = excel.Workbooks;
Workbook wb = books.Add();
Worksheet ws = (Worksheet)wb.Sheets[1];
((Range)ws.Cells[1, 1]).Value = "Hello, COM!";
wb.SaveAs(@"C:\Temp\test.xlsx");
wb.Close();
// Release COM RCW explicitly
Marshal.ReleaseComObject(ws);
Marshal.ReleaseComObject(wb);
Marshal.ReleaseComObject(books);
excel.Quit();
Marshal.ReleaseComObject(excel);Marshal.ReleaseComObject
COM utilise le comptage des références : AddRef/Release. La RCW n'appelle Release que lorsque le GC récupère l'objet, ce qui peut se produire beaucoup plus tard. Appelez Marshal.ReleaseComObject() pour décrémenter immédiatement le compteur de références de la RCW et libérer l'objet COM sans attendre le GC.
// Pattern: release COM objects in finally block
Application? excel = null;
Workbook? wb = null;
try
{
excel = new Application();
wb = excel.Workbooks.Add();
// ... do work ...
}
finally
{
if (wb != null) Marshal.ReleaseComObject(wb);
if (excel != null)
{
excel.Quit();
Marshal.ReleaseComObject(excel);
}
// Force GC to clean up any remaining RCWs
GC.Collect();
GC.WaitForPendingFinalizers();
}HRESULT et exceptions COM
Les méthodes COM renvoient des valeurs HRESULT pour signaler une réussite ou un échec. La RCW vérifie automatiquement le HRESULT et lève une COMException (ou une exception plus spécifique) lorsqu'il indique un échec. Gérez-les avec un bloc try/catch classique.
try
{
// COM method that might fail
Workbook wb = excel.Workbooks.Open(@"C:\missing.xlsx");
}
catch (COMException ex) when (ex.HResult == unchecked((int)0x800A03EC))
{
// Excel-specific HRESULT for file not found
Console.WriteLine($"Excel error: {ex.Message}");
}
catch (COMException ex)
{
// General COM failure
Console.WriteLine($"COM error 0x{ex.HResult:X8}: {ex.Message}");
}Liaison tardive avec dynamic
Si vous ne disposez ni d'une bibliothèque de types ni d'un assembly d'interopérabilité, vous pouvez utiliser le mot-clé C# dynamic pour effectuer une distribution COM avec liaison tardive (IDispatch). Cette approche est plus lente, car les identifiants de distribution sont résolus à l'exécution, mais elle ne nécessite aucun wrapper généré.
// Late-bound COM via dynamic — no interop DLL needed
Type type = Type.GetTypeFromProgID("Word.Application")!;
dynamic word = Activator.CreateInstance(type)!;
word.Visible = false;
dynamic docs = word.Documents;
dynamic doc = docs.Add();
doc.Content.Text = "Late-bound COM example";
doc.SaveAs2(@"C:\Temp\test.docx");
doc.Close();
word.Quit();
Marshal.ReleaseComObject(doc);
Marshal.ReleaseComObject(docs);
Marshal.ReleaseComObject(word);Récepteurs d'événements COM
Les objets COM déclenchent des événements par l'intermédiaire de points de connexion. L'assembly d'interopérabilité génère les interfaces des récepteurs d'événements. Abonnez-vous avec les délégués et événements .NET habituels ; la RCW gère la connexion COM IConnectionPoint.
using Microsoft.Office.Interop.Excel;
Application excel = new Application();
excel.Visible = true;
// Subscribe to COM event via generated event wrapper
excel.WorkbookBeforeClose += (wb, ref cancel) =>
{
Console.WriteLine($"Closing: {wb.Name}");
// Set cancel = true to prevent close
};
excel.WorkbookOpen += (wb) =>
{
Console.WriteLine($"Opened: {wb.Name}");
};
// Open a workbook to trigger events
excel.Workbooks.Open(@"C:\Temp\test.xlsx");Appartements COM : STA et MTA
De nombreux composants COM, notamment ceux liés à l'interface utilisateur comme Office, nécessitent un appartement à thread unique (STA). Marquez toujours les threads qui créent des objets COM STA avec [STAThread] (Main), ou définissez l'état d'appartement du thread avant de le démarrer.
// Console apps default to MTA — COM Office automation requires STA
// Option 1: Mark Main with [STAThread]
[STAThread]
static void Main()
{
var excel = new Microsoft.Office.Interop.Excel.Application();
// ...
}
// Option 2: Run on an STA thread manually
Thread staThread = new Thread(() =>
{
var excel = new Microsoft.Office.Interop.Excel.Application();
// ...
excel.Quit();
Marshal.ReleaseComObject(excel);
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();ComImport et déclarations COM manuelles
Vous pouvez déclarer manuellement des interfaces COM à l'aide des attributs [ComImport], [Guid] et [InterfaceType] ; c'est utile lorsqu'aucune bibliothèque de types n'existe ou lorsque vous n'avez besoin que d'un sous-ensemble d'une grande API COM.
[ComImport]
[Guid("00000000-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IUnknown
{
void QueryInterface(ref Guid riid, out IntPtr ppvObject);
int AddRef();
int Release();
}
// Declare a specific COM interface you want to consume:
[ComImport]
[Guid("0000010C-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPersist
{
void GetClassID(out Guid pClassID);
}Vérification rapide
Quel est le rôle d'une enveloppe appelable à l'exécution (RCW) dans l'interopérabilité COM .NET ?
Récapitulatif : interopérabilité COM et enveloppes appelables à l'exécution
Points essentiels :
- RCW = proxy managé qui encapsule un objet COM ; le CLR en crée automatiquement une par objet COM
- Utilisez
tlbimp.exeou les références VS pour générer des assemblies d'interopérabilité fortement typés - Appelez
Marshal.ReleaseComObject()pour libérer immédiatement les objets COM, sans attendre le GC - Les erreurs COM apparaissent sous forme de
COMExceptionavec le HRESULT d'origine dynamicpermet une distribution COM avec liaison tardive sans assembly d'interopérabilité- Les composants COM d'Office et de l'interface utilisateur nécessitent un thread STA ; utilisez
[STAThread]ou définissez l'état d'appartement
Questions Fréquemment Posées
La leçon « Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution » est-elle gratuite ?
Oui — le texte complet de « Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution » ?
Consommez des composants COM depuis C# avec RCW, importez des bibliothèques de types et gérez les exceptions HRESULT. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C# Academy ?
Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?
Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Fondamentaux de P/Invoke
- LibraryImport et P/Invoke généré à partir du code source
- Code non sécurisé, pointeurs et tampons de taille fixe
- Interopérabilité COM et wrappers appelables depuis l’environnement d’exécution