0Pricing
C# Academy · Lektion

COM-Interop und Runtime Callable Wrappers

Verwenden Sie COM-Komponenten aus C# mit RCW, importieren Sie Typbibliotheken und behandeln Sie HRESULT-Ausnahmen.

COM-Interop und Runtime Callable Wrappers ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist COM-Interop

COM (Component Object Model) ist der ältere binäre Schnittstellenstandard von Microsoft, der weiterhin von Office, der Windows Shell, älteren DirectX-APIs und vielen Unternehmenswerkzeugen verwendet wird. .NET kann COM-Komponenten über Interop-Wrapper nutzen, die zwischen verwalteten Objekten und COM-Schnittstellen übersetzen.

Runtime Callable Wrappers (RCW)

Wenn Sie aus .NET auf ein COM-Objekt zugreifen, erstellt die CLR einen Runtime Callable Wrapper (RCW) – einen verwalteten Proxy, der das COM-Objekt kapselt. Der RCW übernimmt automatisch die Referenzzählung (AddRef/Release), das Apartment-Threading und das Marshalling zwischen COM- und .NET-Typen.

// 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); // ApplicationClass

Typbibliotheken importieren (TLB)

Das Tool tlbimp.exe (Type Library Importer) liest eine COM-Typbibliothek (.tlb oder eingebettet in .dll) und generiert eine .NET-Interop-Assembly mit stark typisierten RCW-Klassen und Schnittstellendefinitionen.

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

Ein COM-Objekt über eine Interop-Assembly verwenden

Sobald Sie die Interop-Assembly referenzieren, sehen COM-Typen wie gewöhnliche .NET-Typen aus. Der Aufruf einer Methode wird über den RCW an einen COM-vtable-Dispatch weitergeleitet. Geben Sie COM-Objekte immer ordnungsgemäß frei, um Ressourcenlecks zu vermeiden.

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 verwendet eine Referenzzählung – AddRef/Release. Der RCW ruft Release erst auf, wenn er von der GC erfasst wird, was deutlich später geschehen kann. Rufen Sie Marshal.ReleaseComObject() auf, um den Referenzzähler des RCW sofort zu verringern und das COM-Objekt freizugeben, ohne auf die GC zu warten.

// 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 und COM-Ausnahmen

COM-Methoden geben HRESULT-Werte zurück, um Erfolg oder Fehler zu signalisieren. Der RCW prüft den HRESULT automatisch und löst eine COMException (oder eine spezifischere Ausnahme) aus, wenn dieser einen Fehler anzeigt. Sie behandeln solche Ausnahmen mit gewöhnlichem try/catch.

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

Late Binding mit dynamic

Wenn keine Typbibliothek oder Interop-Assembly vorhanden ist, können Sie das C#-Schlüsselwort dynamic für spät gebundene COM-Dispatch-Aufrufe (IDispatch) verwenden. Dies ist langsamer, da Dispatch-IDs zur Laufzeit aufgelöst werden, erfordert aber keine generierten Wrapper.

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

COM-Event-Sinks

COM-Objekte lösen Ereignisse über connection points aus. Die Interop-Assembly generiert Event-Sink-Schnittstellen. Sie abonnieren diese mit gewöhnlichen .NET-Delegates und -Events; der RCW übernimmt die COM-IConnectionPoint-Anbindung.

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

COM-Apartments: STA und MTA

Viele COM-Komponenten, insbesondere Benutzeroberflächenkomponenten wie Office, erfordern ein Single-Threaded Apartment (STA). Markieren Sie Threads, die STA-COM-Objekte erstellen, immer mit [STAThread] (Main), oder legen Sie den Apartmentzustand vor dem Starten des Threads fest.

// 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 und manuelle COM-Deklarationen

Sie können COM-Schnittstellen manuell mit den Attributen [ComImport], [Guid] und [InterfaceType] deklarieren – nützlich, wenn keine Typbibliothek vorhanden ist oder Sie nur einen Teil einer großen COM-API benötigen.

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

Schnelltest

Welchen Zweck erfüllt ein Runtime Callable Wrapper (RCW) in der .NET-COM-Interop?

Zusammenfassung: COM-Interop und Runtime Callable Wrappers

Wichtigste Erkenntnisse:

  • RCW = verwalteter Proxy, der ein COM-Objekt kapselt; die CLR erstellt automatisch einen pro COM-Objekt
  • Verwenden Sie tlbimp.exe oder VS References, um stark typisierte Interop-Assemblies zu generieren
  • Rufen Sie Marshal.ReleaseComObject() auf, um COM-Objekte sofort freizugeben (warten Sie nicht auf die GC)
  • COM-Fehler werden als COMException mit dem ursprünglichen HRESULT sichtbar
  • dynamic ermöglicht spät gebundene COM-Dispatch-Aufrufe ohne Interop-Assembly
  • Office-/UI-COM-Komponenten erfordern einen STA-Thread – verwenden Sie [STAThread] oder legen Sie den Apartmentzustand fest

Häufig gestellte Fragen

Ist die Lektion „COM-Interop und Runtime Callable Wrappers“ kostenlos?

Ja — der vollständige Text von „COM-Interop und Runtime Callable Wrappers“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „COM-Interop und Runtime Callable Wrappers“?

Verwenden Sie COM-Komponenten aus C# mit RCW, importieren Sie Typbibliotheken und behandeln Sie HRESULT-Ausnahmen. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „COM-Interop und Runtime Callable Wrappers“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Grundlagen von P/Invoke
  2. LibraryImport und quellcodegeneriertes P/Invoke
  3. Unsicherer Code, Zeiger und feste Puffer
  4. COM-Interop und Runtime Callable Wrappers
← Zurück zu C# Academy