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); // ApplicationClassImportando 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 sinksUsando 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.exeou 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
COMExceptioncom o HRESULT original dynamicpermite 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
- Fundamentos de P/Invoke
- LibraryImport e P/Invoke gerado pela fonte
- Código não seguro, ponteiros e buffers fixos
- Interoperação com COM e wrappers chamáveis em tempo de execução