Todavía es habitual querer invocar procesamiento de .NET 8 desde VBA. En particular, cuando se desea conservar tal cual los activos existentes de Excel o Access, pero delegar en C# únicamente las partes pesadas: procesamiento de cadenas, HTTP, cifrado o lógica de negocio.
Sin embargo, si se recurre al enlace tardío con CreateObject, el lado de VBA termina lleno de Object. IntelliSense pierde fuerza, los errores de tipeo en los nombres de métodos no se detectan hasta la ejecución, y poco a poco se va hundiendo en un terreno cada vez más dependiente de cadenas de texto.
Por eso, en este artículo nos centramos en exponer una DLL de .NET 8 como COM, generar la biblioteca de tipos (TLB) con dscom y usarla desde VBA con tipado mediante enlace temprano.
Dejamos de lado, por ahora, la vieja historia de .NET Framework + RegAsm, la de escribir IDL a mano y compilarlo con MIDL, y la de Reg-Free COM. Aquí tratamos solo el camino directo de .NET 8 / COM host / dscom / enlace temprano en VBA.
El código que aparece en este artículo está publicado en GitHub como un conjunto completo de ejemplos que puede compilar y verificar (biblioteca expuesta a COM, scripts de generación y registro del TLB, módulos de VBA y pruebas unitarias).
dotnet8-dll-typed-vba-com-dscom-tlb - komurasoft-blog-samples (GitHub)
Entorno necesario
| Elemento | Qué se necesita |
|---|---|
| SO | Windows. Como se realiza el registro COM, debe poder ejecutar regsvr32 con permisos de administrador |
| SDK de .NET | SDK de .NET 8. EnableComHosting es una función disponible desde .NET 5 en adelante |
| Office | Excel o Access. Compruebe primero si es la versión de 32 o 64 bits (capítulo 3) |
| Herramienta de generación del TLB | dscom. El método de obtención difiere entre la versión de 64 bits y la de 32 bits (capítulo 6) |
| PC cliente | Runtime de .NET 8 con la misma bitness que Office (capítulo 9) |
Antes de entrar en el procedimiento, se recomienda encarecidamente anotar las versiones de su propio entorno. Si más adelante ocurre que «siguió los mismos pasos pero no funciona», esta es la única información que le permitirá comparar.
# Lista de SDK y runtimes de .NET (también indica si tiene instalado x64 o x86)
dotnet --info
# Número de compilación (build) de Windows
winver
La versión y la bitness de Office se pueden comprobar en Excel desde Archivo > Cuenta > Acerca de Excel. Al final de la línea de título del cuadro de diálogo aparece 32 bits o 64 bits.
1. Conclusión por adelantado
Si adelantamos solo la conclusión, el flujo es el siguiente.
- Compile la biblioteca de clases de .NET 8 con
EnableComHosting=true - Cree una interfaz y una clase explícitas que se expongan a COM
- Deje la clase como
ClassInterfaceType.None, sin recurrir aAutoDual - Marque como
InterfaceIsDualla interfaz que usará VBA - A partir del
*.dllgenerado tras la compilación, cree el*.tlbcondscom tlbexport - Registre
*.comhost.dllconregsvr32 - Registre
*.tlbcondscom tlbregister - Agregue la referencia en VBA y úselo con tipado, como en
Dim x As NombreDeLaLibrería.IYourInterface
En resumen, la arquitectura es esta: la puerta de entrada COM es el *.comhost.dll que genera el SDK de .NET, la información de tipos es el *.tlb que genera dscom, y VBA consulta ese TLB para hacer enlace temprano.
2. Panorama general de esta arquitectura
Primero, veamos en un solo diagrama qué papel cumple cada pieza.
flowchart LR
accTitle: Panorama general de la arquitectura de este artículo
accDescr: VBA obtiene información de tipos del TLB agregado en las referencias y realiza llamadas COM al COM host, que a su vez invoca la DLL de .NET 8, la cual se ejecuta sobre el runtime de .NET 8
VBA["VBA / Excel / Access"] -->|Obtiene información de tipo del TLB agregado en Referencias| TLB["VbaTypedComSample.tlb"]
VBA -->|Llamada COM| COMHOST["VbaTypedComSample.comhost.dll"]
COMHOST --> DOTNET["VbaTypedComSample.dll (.NET 8)"]
DOTNET --> RUNTIME[".NET 8 Runtime"]
El papel de cada archivo es el siguiente.
| Archivo | Papel |
|---|---|
VbaTypedComSample.dll |
Cuerpo de la implementación en .NET 8 |
VbaTypedComSample.comhost.dll |
Puerta de entrada invocada desde COM |
VbaTypedComSample.tlb |
Información de tipos que consulta VBA |
VbaTypedComSample.deps.json |
Información de resolución de dependencias |
VbaTypedComSample.runtimeconfig.json |
Información de arranque del runtime de .NET |
Lo importante aquí es que lo que VBA necesita para conocer los tipos es el TLB, y lo que se necesita como puerta de entrada de arranque COM es el comhost.
El hecho de que no baste con entregar solo el .dll es una de las particularidades poco intuitivas del mundo COM.
3. Lo primero que hay que decidir: hacer coincidir 32 bits y 64 bits
Si se pasa por alto este punto, es bastante probable que termine viendo el mensaje El componente ActiveX no puede crear el objeto.
Haga coincidir la bitness de Office/VBA con la del servidor COM.
| Lado que usa | Referencia del lado de .NET | Generación del TLB | Comando de registro |
|---|---|---|---|
| Office de 64 bits | x64 / win-x64 |
dscom |
C:\Windows\System32\regsvr32.exe |
| Office de 32 bits (en Windows de 64 bits) | x86 / win-x86 |
dscom32.exe |
C:\Windows\SysWOW64\regsvr32.exe |
En el COM host de .NET 5+ en adelante, si se deja AnyCPU tal cual, el *.comhost.dll tiende a generarse del lado de 64 bits, y puede no coincidir con Office de 32 bits. Por eso es más seguro especificar explícitamente x86 / x64 según la versión de Office.
El código de este artículo toma como ejemplo Office de 64 bits. Si usa Office de 32 bits, sustituya más adelante x64 por x86 y win-x64 por win-x86.
4. Construcción del lado de .NET 8
Aquí construiremos un ejemplo mínimo en el que se puedan invocar Add, Divide y Hello desde VBA.
4.1 El archivo .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EnableComHosting>true</EnableComHosting>
<PlatformTarget>x64</PlatformTarget>
<NETCoreSdkRuntimeIdentifier>win-x64</NETCoreSdkRuntimeIdentifier>
</PropertyGroup>
</Project>
El punto clave es EnableComHosting. Al añadirlo, durante la compilación se genera VbaTypedComSample.comhost.dll.
4.2 Dejar todo el ensamblado no visible para COM por defecto
Como solo queremos que los tipos que se van a exponer a COM tengan ComVisible(true), es más cómodo dejar todo el ensamblado en false.
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
4.3 Escribir la interfaz y la clase que se expondrán
using System.Runtime.InteropServices;
namespace VbaTypedComSample;
[ComVisible(true)]
[Guid("2A1BBEDE-DE6E-4C34-AD60-2E9E0E33E999")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICalculator
{
[DispId(1)]
int Add(int x, int y);
[DispId(2)]
double Divide(double x, double y);
[DispId(3)]
string Hello(string name);
}
[ComVisible(true)]
[Guid("FAD1C752-0BB6-4DDD-889F-FE446350847A")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(ICalculator))]
public class Calculator : ICalculator
{
public Calculator()
{
}
public int Add(int x, int y) => checked(x + y);
public double Divide(double x, double y)
{
if (y == 0)
{
throw new ArgumentOutOfRangeException(nameof(y), "No se puede dividir por 0.");
}
return x / y;
}
public string Hello(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return "Hello";
}
return $"Hello, {name}";
}
}
Los puntos que conviene tener en cuenta de este código son los siguientes.
- Asigne
Guidpor separado a la interfaz y a la clase - Use
ClassInterfaceType.Nonepara no depender de la interfaz de clase generada automáticamente - Marque como
InterfaceIsDualpara que sea fácil de manejar desde VBA - Asignar
DispIdayuda a reducir problemas si más adelante se modifica el orden de los métodos ya publicados - Como COM la instancia con
New, prepare un constructor público sin argumentos
5. Compilación
Compile en modo Release.
dotnet build -c Release
Tras la compilación, en la carpeta de salida aparecerán al menos los siguientes archivos.
bin/
Release/
net8.0-windows/
VbaTypedComSample.dll
VbaTypedComSample.comhost.dll
VbaTypedComSample.deps.json
VbaTypedComSample.runtimeconfig.json
Esta es la carpeta que se usa para la distribución y el registro. Si más adelante cambia la ubicación, tendrá que volver a registrar todo.
6. Generar el TLB con dscom
6.1 Qué es dscom
dscom es una herramienta de línea de comandos de código abierto para generar y registrar bibliotecas de tipos (TLB) de COM a partir de ensamblados de .NET. La publica la empresa dSPACE, bajo licencia Apache-2.0.
¿Por qué es necesaria? Porque desde .NET 5 en adelante se eliminaron tlbexp.exe y RegAsm.exe. En la época de .NET Framework, estas dos herramientas permitían generar el TLB y registrar el ensamblado, pero .NET 5+ no incluye de forma estándar un sucesor para ellas. dscom es la herramienta creada para llenar ese vacío.
Basta con recordar estos subcomandos principales.
| Subcomando | Función |
|---|---|
tlbexport |
Exporta el TLB a partir del ensamblado |
tlbregister |
Registra el TLB en el sistema |
tlbunregister |
Anula el registro del TLB |
tlbdump |
Vuelca el contenido del TLB para verificarlo |
tlbembed |
Incrusta el TLB en un archivo |
tlbdump resulta útil para comprobar, antes de abrir VBA, si el TLB generado contiene los tipos previstos.
6.2 Caso de 64 bits
Si solo necesita crear el TLB de 64 bits, puede instalarlo mediante dotnet tool.
dotnet tool install --global dscom
A continuación, genere el TLB a partir del ensamblado compilado.
dscom tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb
6.3 Caso de Office de 32 bits: de dónde obtener dscom32.exe
Este es el punto donde más se suele atascar al dar soporte a Office de 32 bits.
El dscom que se instala con dotnet tool install solo puede manejar ensamblados AnyCPU o de 64 bits, y únicamente puede generar TLB de 64 bits. Para crear un TLB de 32 bits hace falta un ejecutable distinto, dscom32.exe, que no se obtiene de NuGet, sino que se descarga desde la página de lanzamientos (releases) de GitHub.
- Fuente de descarga: https://github.com/dspace-group/dscom/releases
dscom.exe: crea un TLB de 64 bits a partir de un ensamblado AnyCPU o de 64 bitsdscom32.exe: crea un TLB de 32 bits a partir de un ensamblado AnyCPU o de 32 bits
En el ejemplo de este artículo, el dscom32.exe descargado se coloca en la carpeta tools justo debajo del proyecto. La ubicación es libre, pero no lo distribuya junto con la salida de la compilación. Es una herramienta de desarrollo, no algo necesario en tiempo de ejecución.
Hay otro requisito previo que se pasa por alto con facilidad: para ejecutar dscom32.exe es necesario tener instalado el runtime de .NET en la versión x86. Esto se debe a que dscom carga hostfxr.dll, y no funciona en entornos donde solo está instalada la versión x64. Compruebe en la lista que aparece en la salida de dotnet --info si tiene instalado el runtime x86.
.\tools\dscom32.exe tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb
Además, la propia documentación de dscom recomienda que, puesto que dejar AnyCPU tal cual genera *.comhost.dll como de 64 bits, si se va a usar en 32 bits conviene compilar el propio ensamblado en 32 bits. Es la misma conclusión que la del capítulo 3.
Si resulta engorroso ejecutar el comando a mano en cada compilación, puede instalar el paquete dSPACE.Runtime.InteropServices.BuildTasks para generar el TLB automáticamente en el momento de compilar.
7. Registrar el COM host y el TLB
Ejecute esto desde un símbolo del sistema o PowerShell con permisos de administrador.
7.1 Caso de Office de 64 bits / COM de 64 bits
$out = Resolve-Path .\bin\Release\net8.0-windows
C:\Windows\System32\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
dscom tlbregister "$out\VbaTypedComSample.tlb"
7.2 Caso de Office de 32 bits (en Windows de 64 bits)
$out = Resolve-Path .\bin\Release\net8.0-windows
C:\Windows\SysWOW64\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
.\tools\dscom32.exe tlbregister "$out\VbaTypedComSample.tlb"
Aquí se están haciendo dos cosas.
- Registrar
*.comhost.dllcomo servidor COM conregsvr32 - Registrar
*.tlbcomo biblioteca de tipos contlbregister
8. Agregar la referencia en VBA y usarlo con tipado
- Abra Excel o Access
- Abra el editor de VBA (VBE) con
Alt+F11. Si prefiere abrirlo desde la cinta, es la pestañaProgramador>Visual Basic. Si no aparece la pestañaProgramador, actívela desdeArchivo>Opciones>Personalizar cinta de opciones, marcando la casillaProgramador - En el menú del VBE,
Herramientas>Referencias - La lista de
Bibliotecas disponiblesaparece en orden alfabético. Si el registro se realizó correctamente, encontrará ahí el nombre de la biblioteca (por defecto, el mismo que el nombre del ensamblado,VbaTypedComSample); marque la casilla de la izquierda y pulseAceptar - Si no aparece en la lista, selecciónela directamente con el botón
Examinar..., eligiendoVbaTypedComSample.tlb
Si no aparece en la lista, la causa suele ser una de estas dos: una discrepancia de bitness como la del capítulo 3, o que el tlbregister del capítulo 7 no se haya ejecutado correctamente. Desde Office de 32 bits no se ve un TLB registrado en 64 bits.
Para comprobar si la referencia se agregó correctamente, abra Ver > Examinador de objetos (F2) y verifique si puede seleccionar VbaTypedComSample en el selector de biblioteca de la esquina superior izquierda. Si aquí ve ICalculator y Calculator, así como Add / Divide / Hello, significa que el TLB se generó correctamente.
Option Explicit
Public Sub UseCalculator()
Dim calc As VbaTypedComSample.ICalculator
Set calc = New VbaTypedComSample.Calculator
Debug.Print calc.Add(10, 20)
Debug.Print calc.Divide(10, 4)
Debug.Print calc.Hello("VBA")
End Sub
Coloque el cursor en este procedimiento, ejecútelo con F5 y abra la ventana Inmediato con Ctrl + G; verá tres líneas, tal como corresponde a la implementación del capítulo 4.
30
2.5
Hello, VBA
Si esto coincide con lo esperado, significa que todo funciona correctamente: la referencia, el registro COM, el arranque del runtime y el marshaling de argumentos y valores de retorno. Por el contrario, si los valores no coinciden, sospeche de la implementación del lado de .NET; y si directamente no se puede ejecutar, sospeche de los capítulos 3 y 7.
De este modo, del lado de VBA se obtienen estos beneficios.
- IntelliSense funciona
- Es más fácil detectar errores de tipeo en los nombres de métodos antes de ejecutar
- Se puede comprobar la API expuesta en el Examinador de objetos
- Es más legible que escribir todo con
Object
8.1 Las excepciones se convierten en errores COM del lado de VBA
Por ejemplo, si se lanza una excepción del lado de .NET, como en Divide(10, 0), del lado de VBA se ve como un error COM.
Option Explicit
Public Sub UseCalculatorWithErrorHandling()
On Error GoTo EH
Dim calc As VbaTypedComSample.ICalculator
Set calc = New VbaTypedComSample.Calculator
Debug.Print calc.Divide(10, 0)
Exit Sub
EH:
Debug.Print Err.Number
Debug.Print Hex$(Err.Number)
Debug.Print Err.Description
End Sub
Conviene tener claro cómo interpretar los valores que aparecen aquí, para agilizar el diagnóstico.
| Elemento | Qué contiene |
|---|---|
Err.Number |
Contiene el HRESULT correspondiente a la excepción de .NET, como un Long con signo. Como en decimal resulta difícil de leer, conviértalo a hexadecimal con Hex$(Err.Number) |
Err.Description |
A través de IErrorInfo de COM, contiene tal cual el mensaje de la excepción de .NET. En el código anterior, es una cadena que incluye No se puede dividir por 0. |
El valor del HRESULT está determinado por el tipo de excepción. El que corresponde a ArgumentOutOfRangeException es COR_E_ARGUMENTOUTOFRANGE, con el valor 0x80131502. Es decir, si Hex$(Err.Number) resulta en 80131502, significa que ha llegado, tal como se esperaba, el ArgumentOutOfRangeException del lado de .NET.
Los principales son los siguientes.
| Excepción de .NET | Constante HRESULT | Valor |
|---|---|---|
ArgumentException |
COR_E_ARGUMENT |
0x80070057 |
ArgumentOutOfRangeException |
COR_E_ARGUMENTOUTOFRANGE |
0x80131502 |
InvalidOperationException |
COR_E_INVALIDOPERATION |
0x80131509 |
NotSupportedException |
COR_E_NOTSUPPORTED |
0x80131515 |
| Otras excepciones generales distintas de las anteriores | COR_E_EXCEPTION |
0x80131500 |
Si desea diferenciar el tratamiento según el tipo de excepción del lado de VBA, tendrá que ramificar según este HRESULT. Sin embargo, un diseño que ramifica según el HRESULT es frágil ante cambios en el tipo de excepción del lado de .NET, así que para los fallos de negocio resulta más estable devolver un valor de retorno o un código de error, en lugar de una excepción, como límite entre ambos mundos.
9. Consideraciones al distribuir
Lo importante al distribuir es colocar todo el conjunto de la salida, en lugar de repartir solo la DLL.
VbaTypedComSample.dll
VbaTypedComSample.comhost.dll
VbaTypedComSample.deps.json
VbaTypedComSample.runtimeconfig.json
VbaTypedComSample.tlb
(si es necesario, el conjunto de DLL de dependencias)
Además, el PC cliente necesita el runtime de .NET 8 correspondiente. El COM host no se distribuye como self-contained, sino que, básicamente, funciona en modo framework-dependent.
En concreto, esto es lo que hay que instalar.
- La página de distribución es Descargas de .NET 8
- Lo que se necesita no es el SDK, sino el runtime. Como el ejemplo de este artículo es una biblioteca de clases sin interfaz gráfica, basta con
.NET Runtime. Si se usan tipos de WPF o Windows Forms, se necesita.NET Desktop Runtime - La bitness debe coincidir con la de Office. Si Office es de 64 bits, use el runtime x64; si es de 32 bits, use x86. Por el mismo motivo por el que en el capítulo 3 se especificó explícitamente
x64/x86, aquí también fallará el arranque si no coincide - Para saber si ya está instalado, ejecute
dotnet --list-runtimesen el PC cliente y compruebe si aparece una línea conMicrosoft.NETCore.App 8.x
Asegúrese de anotar en el material de distribución este «tipo, versión y bitness del runtime necesario». Si se olvida de incluirlo en el procedimiento de instalación, en el sitio del cliente acabarán viendo El componente ActiveX no puede crear el objeto., sospechando de la bitness y perdiendo tiempo.
10. Errores comunes (puntos donde se suele atascar)
10.1 No dejar AnyCPU sin cambiar
Si la bitness de VBA/Office y la del COM host no coinciden, se produce un tipo de fallo bastante desconcertante.
- Si es Office de 64 bits:
x64/win-x64 - Si es Office de 32 bits:
x86/win-x86
10.2 No usar ClassInterfaceType.AutoDual
A primera vista resulta cómodo, pero es fácil de romper si se modifica el orden o la composición de los miembros después de publicarlo.
Si quiere usarlo de forma estable y con tipado desde VBA, la práctica habitual es definir una interfaz explícita y dejar la clase como ClassInterfaceType.None.
10.3 No regenerar el GUID a la ligera
En COM, el GUID es en sí mismo el contrato. Si se sustituye el IID o el CLSID a la ligera después de publicarlo, se rompen las referencias y los registros existentes en VBA.
10.4 No romper interfaces ya publicadas
En COM, incluso algo tan aparentemente inofensivo como «añadir un solo método más tarde» puede no salir bien parado.
- Conserve
ICalculator - Si el cambio es grande, cree una nueva
ICalculator2 - La clase puede implementar ambas
10.5 Preferir tipos sencillos y discretos
En el límite que se expone a VBA, es más seguro no complicarse demasiado.
Para empezar, los tipos que funcionan bien son estos.
intdoubleboolstringDateTimedecimalenum
10.6 No actualizar con Office abierto
Excel o Access pueden quedarse reteniendo la DLL, lo que puede causar problemas al compilar o volver a registrar.
- Cierre Office
- Anule el registro si es necesario
- Vuelva a compilar
- Registre de nuevo
La anulación del registro se realiza en el orden inverso al del registro, usando el comando de la misma bitness que se utilizó para registrar. También aquí se necesitan permisos de administrador, igual que al registrar.
# Caso de Office de 64 bits / COM de 64 bits
$out = Resolve-Path .\bin\Release\net8.0-windows
dscom tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\System32\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"
# Caso de Office de 32 bits (en Windows de 64 bits)
$out = Resolve-Path .\bin\Release\net8.0-windows
.\tools\dscom32.exe tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\SysWOW64\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"
La opción /u de regsvr32 es la de anulación de registro. Si usa un regsvr32 distinto del que usó para registrar, no podrá anularlo (lo que se registró en 64 bits no se puede quitar con el regsvr32 de SysWOW64). Si no anula el registro antes de mover o eliminar toda la carpeta, quedará en el registro una entrada que apunta a una ruta que ya no existe.
11. Resumen
El tema de «usar una DLL de .NET 8 con tipado desde VBA» no resulta un procedimiento tan intimidante si se centra en exponerla a COM y generar el TLB con dscom. Del lado de .NET 8, active EnableComHosting=true y prepare una interfaz explícita (la clase como ClassInterfaceType.None, y la orientada a VBA como InterfaceIsDual); cree el TLB con dscom tlbexport; registre *.comhost.dll con regsvr32 y *.tlb con dscom tlbregister. Después, solo queda agregar la referencia en VBA y usar el enlace temprano.
Cuando tenga dudas, el truco es pensar por separado en el COM host y en el TLB.
- La puerta de entrada de arranque es
*.comhost.dll - La información de tipos es
*.tlb - El cuerpo de la implementación es
*.dll
12. Referencias
- Conjunto completo del código de ejemplo de este artículo (biblioteca expuesta a COM, scripts, VBA, pruebas) - komurasoft-blog-samples (GitHub)
- Expose .NET components to COM - Microsoft Learn
- Calificar tipos de .NET para la interoperabilidad COM - Microsoft Learn
- Enumeración ComInterfaceType - Microsoft Learn
- Enumeración ClassInterfaceType - Microsoft Learn
- Contenedor invocable desde COM - Microsoft Learn
- Clase DispIdAttribute - Microsoft Learn
- dscom - NuGet Gallery
- dspace-group/dscom - GitHub (el propio dscom; incluye la lista de subcomandos y la explicación del soporte de 32 bits)
- Página de lanzamientos de dscom (de donde se obtiene
dscom32.exe) - Cómo asignar HRESULT y excepciones - Microsoft Learn
- How to use the Regsvr32 tool and troubleshoot Regsvr32 error messages - Microsoft Support
- Descargas de .NET 8
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
El problema de EXCEL.EXE que permanece al operar Excel desde C# — Patrones de liberación de referencias COM y el criterio de sustitución
Explica por qué EXCEL.EXE permanece al operar Excel vía COM desde C#, mediante el conteo de referencias COM y el RCW. Cubre la regla de l...
Migrar macros VBA de Excel a Power Automate — qué reemplazar con Office Scripts y qué mantener en VBA
Analizamos si las macros VBA de Excel migran a Power Automate: alcance de Office Scripts, límites del conector, licencias y migración por...
Compatibilidad retroactiva de interfaces DLL y COM — Tabla de decisión sobre qué cambios rompen al lado que llama
Qué cambios de DLL o COM rompen al lado que llama: los tres niveles de compatibilidad, la tabla de decisión por cambio y la regla de inmu...
¿Las aplicaciones empresariales funcionan en Windows para Arm? — La realidad de la emulación x64 (Prism), las DLL nativas y COM
Respondemos si las aplicaciones empresariales funcionan en Windows para Arm: la emulación x64 (Prism), las capas que no funcionan (contro...
Cómo elegir la comunicación entre procesos en Windows — canalizaciones con nombre / TCP / gRPC / memoria compartida / COM: tabla de decisión
Cómo elegir la comunicación entre procesos en Windows: comparamos en una tabla de decisión las canalizaciones con nombre, el TCP local, g...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Migración de ActiveX
Decisiones para conservar, encapsular o sustituir componentes COM / ActiveX / OCX.
Servicios relacionados con este tema
El artículo está directamente relacionado con los siguientes servicios.
Desarrollo de aplicaciones para Windows
El diseño de la superficie de conexión entre VBA, COM, Office, .NET 8 y la generación de la biblioteca de tipos está muy ligado al desarrollo de aplicaciones para Windows, por lo que encaja bien con el desarrollo de aplicaciones Windows.
Consultoría técnica y revisión de diseño
Si desea ordenar el diseño del límite que conecta los activos existentes de VBA con .NET 8, incluyendo la bitness, el registro, la generación del TLB y el método de distribución, es un tema que se presta bien a una consultoría técnica y revisión de diseño.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Qué se necesita para usar una DLL de .NET 8 desde VBA con tipado (enlace temprano)?
- Compile la biblioteca de clases de .NET 8 con EnableComHosting=true para generar *.comhost.dll, y cree *.tlb con dscom tlbexport. A continuación registre *.comhost.dll con regsvr32 y *.tlb con dscom tlbregister; si añade ese TLB en las referencias de VBA, podrá usarlo con tipado de la forma Dim x As NombreDeLaLibrería.IYourInterface. En cuanto al reparto de roles: *.comhost.dll es la puerta de entrada COM, *.tlb es la información de tipos que ve VBA, y *.dll es el cuerpo de la implementación.
- ¿Cuál es la causa del mensaje «El componente ActiveX no puede crear el objeto»?
- La causa típica es una discrepancia de bitness entre Office/VBA y el servidor COM. Si es Office de 64 bits, compile con x64/win-x64 y registre con el regsvr32 de System32; si es Office de 32 bits (sobre Windows de 64 bits), compile con x86/win-x86 y registre con el regsvr32 de SysWOW64, usando también dscom32.exe para generar el TLB. En el COM host de .NET 5 en adelante, si se deja AnyCPU tal cual, *.comhost.dll tiende a generarse del lado de 64 bits, lo que puede no coincidir con Office de 32 bits; por eso es más seguro especificar explícitamente x86/x64 según la versión de Office.
- ¿No se debe usar ClassInterfaceType.AutoDual?
- A primera vista parece cómodo, pero debe evitarse porque es fácil de romper si se modifica el orden o la composición de los miembros después de publicarlo. Si quiere usarlo de forma estable y con tipado desde VBA, la práctica habitual es definir una interfaz explícita, dejar la clase como ClassInterfaceType.None y marcar la interfaz que usa VBA como InterfaceIsDual. Asignar DispId ayuda a reducir problemas cuando cambia el orden de los métodos. Además, en COM el GUID es en sí mismo el contrato, así que si se regenera el IID o el CLSID a la ligera después de publicarlo, se rompen las referencias y los registros existentes en VBA.
- ¿Basta con entregar solo la DLL al distribuir?
- No, con la DLL sola no funciona. Debe colocar juntos el *.dll del cuerpo de la implementación, *.comhost.dll, *.deps.json, *.runtimeconfig.json, *.tlb y, si es necesario, el conjunto de DLL de dependencias. Además, el PC cliente necesita el runtime de .NET 8 correspondiente, ya que el COM host no se distribuye como self-contained sino que, básicamente, funciona en modo framework-dependent. Tenga en cuenta también que, si más adelante cambia la ubicación de los archivos, tendrá que volver a registrar todo.
Perfil del autor
Página de presentación del autor del artículo.
Go Komura
Representante de KomuraSoft LLC
Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.