0Pricing
C# Academy · Aula

Interoperação com COM e wrappers chamáveis em tempo de execução

Consuma componentes COM do C# com RCW, importe bibliotecas de tipos e trate exceções HRESULT.

Interoperação com COM e wrappers chamáveis em tempo de execução é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

O que é interoperabilidade COM?

COM (Modelo de Objetos de Componentes) é o padrão de interface binária legado da Microsoft, ainda usado pelo Office, pelo Windows Shell, pelas APIs legadas do DirectX e por muitas ferramentas corporativas. O .NET pode consumir componentes COM por meio de wrappers de interoperabilidade que fazem a conversão entre objetos gerenciados e interfaces COM.

Adaptadores chamáveis em tempo de execução (RCW)

Quando você acessa um objeto COM a partir do .NET, o CLR cria uma Runtime Callable Wrapper (RCW) — um proxy gerenciado que encapsula o objeto COM. A RCW gerencia automaticamente a contagem de referências (AddRef/Release), a execução em apartamentos e a conversão entre tipos COM e .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); // ApplicationClass

Importando bibliotecas de tipos (TLB)

A ferramenta tlbimp.exe (Importador de Bibliotecas de Tipos) lê uma biblioteca de tipos COM (.tlb ou incorporada em .dll) e gera uma biblioteca de interoperabilidade .NET com classes RCW fortemente tipadas e definições de interfaces.

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

Usando um objeto COM por meio de uma biblioteca de interoperabilidade

Depois que você faz referência à biblioteca de interoperabilidade, os tipos COM se comportam como tipos .NET comuns. A chamada de um método é traduzida por meio da RCW para um despacho pela tabela virtual COM. Sempre libere os objetos COM corretamente para evitar vazamentos de recursos.

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 usa contagem de referências — AddRef/Release. A RCW chama Release somente quando é coletada pelo coletor de lixo, o que pode acontecer muito mais tarde. Chame Marshal.ReleaseComObject() para diminuir imediatamente a contagem de referências da RCW e liberar o objeto COM sem esperar pelo coletor de lixo.

// 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 e exceções COM

Os métodos COM retornam valores HRESULT para indicar sucesso ou falha. A RCW verifica automaticamente o HRESULT e lança uma COMException (ou uma exceção mais específica) quando ele indica uma falha. Você as trata normalmente com 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}");
}

Vinculação tardia com dynamic

Se you não tiver uma biblioteca de tipos ou uma biblioteca de interoperabilidade, pode usar a palavra-chave dynamic do C# para o despacho COM com vinculação tardia (IDispatch). Isso é mais lento — os identificadores de despacho são resolvidos em tempo de execução —, mas não exige wrappers gerados.

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

Receptores de eventos COM

Os objetos COM disparam eventos por meio de pontos de conexão. A biblioteca de interoperabilidade gera interfaces receptoras de eventos. Você se inscreve usando delegados e eventos .NET normais, e a RCW gerencia a infraestrutura 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");

Apartamentos COM: STA versus MTA

Muitos componentes COM, especialmente os relacionados à interface do usuário, como os do Office, exigem um apartamento de thread única (STA). Sempre marque as linhas de execução que criam objetos COM STA com [STAThread] (Main) ou defina o estado do apartamento da linha de execução antes de iniciá-la.

// 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 e declarações COM manuais

É possível declarar interfaces COM manualmente usando os atributos [ComImport], [Guid] e [InterfaceType] — algo útil quando não existe uma biblioteca de tipos ou quando você precisa apenas de um subconjunto de uma API COM grande.

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

Verificação rápida

Qual é a finalidade de um Runtime Callable Wrapper (RCW) na interoperabilidade COM do .NET?

Recapitulação: interoperabilidade COM e adaptadores chamáveis em tempo de execução

Principais conclusões:

  • RCW = proxy gerenciado que encapsula um objeto COM; o CLR cria um automaticamente para cada objeto COM
  • Use tlbimp.exe ou as Referências do VS para gerar bibliotecas de interoperabilidade fortemente tipadas
  • Chame Marshal.ReleaseComObject() para liberar objetos COM imediatamente, sem esperar pelo coletor de lixo
  • Os erros COM aparecem como COMException com o HRESULT original
  • dynamic permite o despacho COM com vinculação tardia sem uma biblioteca de interoperabilidade
  • Os componentes COM do Office e da interface do usuário exigem uma linha de execução STA — use [STAThread] ou defina o estado do apartamento

Perguntas Frequentes

A aula “Interoperação com COM e wrappers chamáveis em tempo de execução” é grátis?

Sim — o texto completo de “Interoperação com COM e wrappers chamáveis em tempo de execução” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “Interoperação com COM e wrappers chamáveis em tempo de execução”?

Consuma componentes COM do C# com RCW, importe bibliotecas de tipos e trate exceções HRESULT. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Interoperação com COM e wrappers chamáveis em tempo de execução”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Fundamentos de P/Invoke
  2. LibraryImport e P/Invoke gerado pela fonte
  3. Código não seguro, ponteiros e buffers fixos
  4. Interoperação com COM e wrappers chamáveis em tempo de execução
← Voltar para C# Academy