¿Qué es Reg-Free COM? - El mecanismo para usar COM sin registro
· Actualizado el: · Go Komura · COM, Reg-Free COM, Registration-Free COM, Desarrollo en Windows, Tecnología heredada
En los proyectos de COM / ActiveX / OCX aparecen los mismos problemas cada vez que hay que distribuir o actualizar la aplicación.
- Se necesita
regsvr32 - Suele requerir privilegios de administrador
- Choca con otra versión que ya instaló otra aplicación
- Al desinstalar, arrastra a otros productos
- Funciona en la máquina de desarrollo, pero no en un entorno limpio
Reg-Free COM permite reducir bastante estas molestias. Sin embargo, a pesar de su nombre, no es «una magia que elimina por completo las molestias de COM». Lo que desaparece es, sobre todo, la carga que arrastra el registro global. No hace desaparecer las dificultades relacionadas con la bitness, las DLL dependientes, las bibliotecas de tipos ni el modelo de subprocesos.
En este artículo organizamos Reg-Free COM centrándonos en el contexto de usar COM DLL / OCX de forma local a la aplicación en aplicaciones de escritorio Windows.
Público objetivo y requisitos previos
Este artículo está dirigido a desarrolladores que distribuyen aplicaciones de escritorio Windows que usan COM DLL / OCX existentes y quieren dejar atrás regsvr32 y los privilegios de administrador. Se asume que ya ha tenido contacto al menos una vez con los fundamentos de COM (CLSID, ProgID, CoCreateInstance, servidor in-proc). Si todavía tiene dudas al respecto, es más rápido leer primero «¿Qué es COM / ActiveX / OCX? - Diferencias y relación explicadas».
La parte de procedimientos usa mt.exe y sxstrace del Windows SDK, así que se asume un entorno con Visual Studio o el Windows SDK instalado.
1. Primero, la conclusión en pocas palabras
Dicho de forma directa pero útil, es esto:
- Reg-Free COM es una forma de mantener la información de registro de COM en un manifiesto en lugar de en el registro de Windows
- En tiempo de ejecución, al resolver
CoCreateInstanceoCLSIDFromProgID, primero se consulta el contexto de activación - Por eso es posible mantener la COM DLL / OCX de forma privada por cada aplicación
- Sus principales ventajas son facilitar la distribución por copia directa (XCOPY), evitar más fácilmente los conflictos de versión y reducir el riesgo de que una desinstalación quede rota
- Sin embargo, el problema de 32 bits / 64 bits no desaparece. Esto no se puede evitar con la forma de escribir el manifiesto
- Además, hay que seguir considerando por separado las DLL dependientes, las bibliotecas de tipos, las referencias en tiempo de diseño y las dependencias de registro no estándar
- En la práctica, encaja bastante bien cuando se quiere aislar componentes COM propios de una aplicación
En resumen, Reg-Free COM es un mecanismo que devuelve la activación de COM al ámbito de cada aplicación.
2. Reg-Free COM en el sentido de este artículo
Reg-Free COM es la abreviatura de Registration-Free COM. En español a veces se lo llama «COM sin registro».
Aquí, «sin registro» significa que no se depende por completo del registro global de Windows (HKCR / CLSID / InprocServer32, etc.) para usar COM.
No significa que desaparezca el propio COM, ni que deje de hacer falta el GUID.
Los objetos principales de este artículo son los siguientes:
- COM DLL nativas
- Servidores COM basados en ATL
- ActiveX / OCX
- Interoperabilidad COM basada en .NET Framework
- Exposición mediante el COM host de .NET 5+ / .NET 8
Y, al contrario, hay dos puntos que quiero recalcar en este artículo:
- Reg-Free COM trata sobre la «activación»
- La distribución de información de tipos y la configuración de referencias en tiempo de diseño pueden quedar como cuestiones aparte
Mezclar estos dos puntos hace que la discusión se vuelva bastante confusa.
3. Un vistazo general primero
Antes de entrar en el diagrama, conviene definir de antemano los cuatro términos que aparecen una y otra vez en este artículo.
| Término | Significado |
|---|---|
| Contexto de activación (activation context) | Es una estructura de datos en tiempo de ejecución que mantiene «qué versión de qué assembly está usando este hilo ahora mismo». CoCreateInstance la consulta antes que el registro |
| side-by-side assembly | Es el mecanismo de Windows para que componentes con el mismo nombre pero distintas versiones coexistan en la misma máquina. Se identifica mediante un manifiesto, donde assemblyIdentity funciona como etiqueta de identificación |
| Manifiesto de la aplicación | Es el XML asociado al EXE, donde se declara «de qué side-by-side assembly depende este programa» |
| Manifiesto del componente (assembly manifest) | Es el XML asociado al componente, donde se declara «qué archivos incluye este assembly y qué clases COM expone». Aquí se traslada la información que antes residía en el registro |
El contexto de activación se mantiene por hilo. COM traspasa el contexto de activación del hilo que crea el objeto al hilo del host antes de llamar a LoadLibrary o DllGetClassObject, así que el lado que hace la llamada no necesita preparar nada especial.
Dicho esto, es más rápido ver el panorama completo de un vistazo.
flowchart LR
accTitle: Flujo de resolución de Reg-Free COM
accDescr: Diagrama que muestra cómo MyApp.exe depende de su manifiesto de aplicación, que declara una dependentAssembly resuelta por el manifiesto del componente hacia el archivo, la clase COM y la biblioteca de tipos que apuntan a la DLL, y cómo en paralelo el contexto de activación de la aplicación es consultado por CLSIDFromProgID o CoCreateInstance para llegar a la misma DLL
APP["MyApp.exe"] --> AM["Application Manifest"]
AM --> DEP["dependentAssembly"]
DEP --> CM["Component / Assembly Manifest"]
CM --> META["file / comClass / typelib"]
META --> DLL["VendorControl.dll / .ocx"]
APP --> ACTX["Activation Context"]
ACTX --> COM["CLSIDFromProgID / CoCreateInstance"]
COM --> DLL
En COM normal, al llamar a CoCreateInstance, se recorre el registro para decidir qué DLL cargar.
En Reg-Free COM, antes de eso se consulta el contexto de activación actualmente vigente, y se resuelve a partir de la información del manifiesto escrita allí.
Por esto, en la misma máquina resulta más fácil que la aplicación A y la aplicación B trabajen cada una con una versión distinta del mismo componente COM. Es, en cierto modo, devolver un poco la cultura compartida de COM hacia un enfoque más local a la aplicación.
4. Por qué la distribución COM tradicional tiende a ser pesada
La distribución COM tradicional es pesada no tanto porque COM en sí sea malo, sino porque parte de la premisa del registro global.
Para usar una clase COM se necesita, a grandes rasgos, esta información:
| Información | Función |
|---|---|
| CLSID | El GUID que identifica de forma única a la clase |
| ProgID | Un nombre fácil de manejar para las personas |
| InprocServer32 | Indica qué DLL cargar |
| ThreadingModel | La premisa del modelo de subprocesos, como Apartment o Both |
| TypeLib | La información de tipos |
Cuando esta información entra en el registro, resulta conveniente para toda la máquina, porque es fácil compartirla entre varias aplicaciones.
Sin embargo, en la práctica, este mismo hecho de compartir se vuelve en contra.
- El instalador de un producto sobrescribe el registro COM de otro producto
- Un desinstalador «cree que solo está borrando lo suyo» y rompe un COM compartido
- El registro que casualmente está presente en la máquina de desarrollo no existe en la máquina de producción
- El registro de 32 bits y el de 64 bits no coinciden, y el síntoma se manifiesta de forma inquietante y desajustada
Es decir, con bastante frecuencia es el modelo de distribución, más que COM en sí, lo que da problemas a la gente. Reg-Free COM es un mecanismo para reducir esta dificultad del modelo de distribución.
5. El funcionamiento de Reg-Free COM
5.1 Declarar las dependencias en el manifiesto de la aplicación
Primero, el lado de la aplicación declara de qué side-by-side assembly depende en el manifiesto de la aplicación.
Este manifiesto se puede manejar de dos formas:
- Colocarlo junto al EXE, con un nombre como
MyApp.exe.manifest - Incrustarlo como recurso dentro del EXE
En la práctica, es habitual elegir el archivo externo cuando se quiere facilitar la distribución y el reemplazo, e ir a la incrustación cuando se prioriza la robustez y la simplicidad de la distribución.
Además, cuando existen tanto la versión de archivo externo como la incrustada, tiene prioridad el manifiesto presente en el sistema de archivos.
5.2 Registrar la información COM en el manifiesto del componente
A continuación, el lado de COM mantiene en el manifiesto del componente la información que originalmente residía en el registro.
Aquí se incluye, por ejemplo, información como esta:
comClassclsidprogidthreadingModeltypelib- si hace falta, proxy / stub, clases de ventana, etc.
En otras palabras, la idea es describir en XML el «aspecto» de COM, en lugar de guardarlo en el registro.
Este manifiesto se puede configurar de dos formas:
- Colocarlo en un archivo separado de la DLL
- Incrustarlo como recurso dentro de la DLL
En la práctica, incrustarlo en la DLL como private assembly suele generar menos incidentes. Manejarlo como archivo separado es fácil de entender, pero es más propenso a tropiezos por la correspondencia entre el nombre de archivo y el assemblyIdentity, la ubicación de los archivos y las copias olvidadas.
5.3 En tiempo de ejecución se consulta primero el contexto de activación
Aquí está el núcleo de Reg-Free COM.
Cuando la aplicación llama a CLSIDFromProgID o CoCreateInstance, el runtime de COM consulta el contexto de activación activo.
Si allí está la información necesaria de ProgID → CLSID y CLSID → DLL, puede resolverse sin usar el registro.
Por el contrario, si falta información necesaria en el manifiesto, se recurre a la resolución tradicional basada en registro. Este comportamiento provoca una trampa: funciona por casualidad en la máquina de desarrollo. Se cree que la configuración quedó como Reg-Free, cuando en realidad se está apoyando en un registro local.
Esta es la trampa más traicionera de Reg-Free COM.
6. Qué ventajas ofrece
Las ventajas de Reg-Free COM son bastante claras en la práctica.
6.1 Facilita la distribución por copia directa (XCOPY)
Como se pueden reunir todos los archivos necesarios en la carpeta de la aplicación, el instalador y el proceso de registro se vuelven más ligeros.
Por supuesto, escribir dentro de Program Files es otra cuestión en materia de permisos, pero al menos suele ser posible reducir el trabajo administrativo necesario para el registro de COM.
6.2 Reduce los conflictos de versión
Aunque en la misma máquina haya varias versiones de un componente COM, resulta más fácil separar la versión que usa cada aplicación. Esto ayuda bastante a evitar el incidente de «el comportamiento cambió de repente por la instalación de otro producto».
6.3 En muchos casos no hace falta modificar demasiado el código existente
Reg-Free COM es un mecanismo que cambia la forma de resolución, más que obligar a rehacer desde la raíz la forma en que se llama al código existente.
Por eso, cuando encaja bien, se puede introducir tocando muy poco el código del lado de CoCreateInstance.
6.4 Facilita la eliminación y la reversión
Al quedar todo contenido dentro del ámbito de la aplicación, las actualizaciones y las reversiones se vuelven bastante más sencillas. Llevado al extremo, se vuelve viable la idea de reemplazar toda la carpeta.
7. Escenarios adecuados y no adecuados
7.1 Escenarios adecuados
En casos como estos, Reg-Free COM es bastante recomendable:
| Situación | Compatibilidad |
|---|---|
| Se quiere incluir una COM DLL / OCX exclusiva de la aplicación | Muy buena |
| Se quiere que convivan varias versiones en el mismo PC | Muy buena |
| Se quiere evitar incidentes de registro provocados por componentes de proveedores | Buena |
| Se quiere usar ActiveX / OCX de forma privada en una aplicación de escritorio existente | Buena |
| Se quiere aligerar la distribución sin cambiar mucho las llamadas existentes | Buena |
Típicamente, encaja bien con aplicaciones de escritorio de negocio, herramientas de integración con equipos y activos existentes en VB6 / MFC / WinForms.
7.2 Escenarios no adecuados, o que requieren cautela
Por otro lado, hay casos en los que conviene ser cauteloso:
| Situación | Comentario |
|---|---|
| Se quiere compartir COM en toda la máquina | El beneficio de Reg-Free se diluye |
| La bitness no coincide | Reg-Free no lo resuelve |
| Hay una fuerte dependencia de información de registro no estándar o de instaladores propios | Es difícil convertirlo en manifiesto |
| No está resuelta la distribución de las DLL dependientes o del runtime de VC++ | Al final el fallo aparece en otro lugar |
| Las herramientas de diseño o la configuración de referencias del IDE dan por hecho el registro | Se necesita un diseño operativo distinto |
Este último punto en particular es importante. Reg-Free COM ayuda con la activación en tiempo de ejecución, pero no cambia de un plumazo lo que da por supuesto la interfaz de configuración de referencias en tiempo de diseño.
8. Malentendidos habituales
8.1 «Con Reg-Free COM desaparece el problema de bitness»
No desaparece. Un proceso de 32 bits solo puede cargar una COM DLL in-proc de 32 bits, y un proceso de 64 bits solo puede cargar una DLL de 64 bits. En esto, Reg-Free se comporta igual que siempre.
8.2 «Con Reg-Free COM nunca se consulta el registro»
Esto también es incorrecto. Si falta información necesaria en el manifiesto, se recurre a la resolución tradicional basada en registro. Por eso, que funcione en la máquina de desarrollo no significa necesariamente que la configuración Reg-Free sea correcta.
8.3 «Con Reg-Free COM el tema de la biblioteca de tipos también se resuelve automáticamente»
Esto solo es cierto en parte.
En el manifiesto también se puede escribir información de typelib, pero es normal que el manejo de la información de tipos —como la configuración de referencias en VBA, el #import de C++ o la generación de referencias en tiempo de diseño en .NET— requiera un diseño aparte.
Reg-Free COM trata, ante todo, de conseguir que la aplicación se inicie. Cómo desarrollar de forma tipada es el siguiente punto a resolver.
8.4 «Con Reg-Free COM cualquier ActiveX / OCX funciona tal cual»
Esto también es peligroso. Si el componente sigue la información de registro COM estándar, es fácil avanzar, pero si depende mucho de configuraciones de registro propias, instaladores adicionales, procesamiento de licencias o un grupo aparte de módulos, la conversión a Reg-Free se complica de golpe.
8.5 «Reg-Free COM es más o menos lo mismo en .NET Framework y en .NET 8»
Hay puntos parecidos, pero la cadena de herramientas es bastante distinta.
El contexto de .NET Framework + RegAsm y el de .NET 5+ / .NET 8 + comhost son, aunque ambos son COM, terrenos diferentes.
9. Diferencias entre nativo, .NET Framework, .NET 5+ y .NET 8
Este punto tiende a mezclarse, así que conviene separarlo aquí.
| Familia | Resumen general |
|---|---|
| COM DLL / OCX nativas | La base es pensarlo en términos de manifiesto de la aplicación + manifiesto del componente |
| Interoperabilidad COM basada en .NET Framework | Además del manifiesto de la aplicación al estilo Win32, también hace falta el manifiesto del lado del componente administrado |
| Exposición COM en .NET 5+ / .NET 8 | Con EnableComHosting se crea el COM host, y con EnableRegFreeCom se puede generar el manifiesto para Reg-Free COM |
9.1 COM basado en .NET Framework
En COM basado en .NET Framework se necesitan dos capas: el manifiesto de la aplicación al estilo Win32 del lado de la aplicación COM y el manifiesto del componente del lado del componente administrado.
Es decir, respecto a COM nativo, hay un manifiesto más. Las restricciones de nombre e ID de recurso del punto 10.4 se aplican de la misma manera a este manifiesto del componente.
9.2 Exposición de COM en .NET 5+ / .NET 8
En .NET 5+ / .NET 8, el punto de entrada para la exposición COM es *.comhost.dll.
Además, si se activa EnableRegFreeCom=true, se genera el manifiesto side-by-side para Reg-Free COM.
Como se explica en 8.3, el manejo de la información de tipos queda como una cuestión aparte, pero en .NET Core / .NET 5+ esto cambia todavía más. Ya no es, como en la época de .NET Framework, un mundo en el que el TLB surge de forma natural a partir del ensamblado, así que si se necesita un uso tipado, hace falta organizar por separado la generación, incrustación y registro del TLB. Los pasos concretos están recogidos en «Cómo usar una DLL de .NET 8 desde VBA de forma tipada - Exposición COM y TLB con dscom».
10. Ejemplo de configuración mínima
Aquí mostramos un ejemplo mínimo en el que MyApp.exe usa Vendor.CameraControl.dll mediante Reg-Free COM.
10.1 Estructura de archivos de ejemplo
MyApp.exe
MyApp.exe.manifest
Vendor.CameraControl.Asm.manifest
Vendor.CameraControl.dll
Vendor.Helper.dll
En el ejemplo anterior se asume que el manifiesto del componente se coloca en un archivo separado. También es posible incrustarlo en la DLL, pero en ese caso el nombre del assembly y el ID de recurso quedan sujetos a restricciones concretas. Este procedimiento se trata paso a paso en 10.4.
10.2 Ejemplo de manifiesto de la aplicación
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="KomuraSoft.MyApp"
version="1.0.0.0"
processorArchitecture="amd64" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Vendor.CameraControl.Asm"
version="1.0.0.0"
processorArchitecture="amd64" />
</dependentAssembly>
</dependency>
</assembly>
10.3 Ejemplo de manifiesto del componente
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Vendor.CameraControl.Asm"
version="1.0.0.0"
processorArchitecture="amd64" />
<file name="Vendor.CameraControl.dll">
<comClass
clsid="{01234567-89AB-CDEF-0123-456789ABCDEF}"
progid="Vendor.CameraControl.1"
threadingModel="Apartment"
tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}" />
<typelib
tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}"
version="1.0"
helpdir="" />
</file>
</assembly>
En este ejemplo, lo verdaderamente importante no son los detalles del XML, sino que el dependentAssembly del lado de la aplicación coincida con el assemblyIdentity del lado del componente.
Si esto se desajusta, se produce un fallo de inicio cuya causa no se puede deducir solo con el aspecto del error.
Tenga en cuenta que el GUID y los nombres anteriores son solo ejemplos explicativos. En la práctica, hay que escribirlos correctamente conforme al CLSID / TLBID / ProgID / modelo de subprocesos que expone realmente el componente.
10.4 Dónde colocar el manifiesto y cómo incrustarlo
Este es el punto donde más se tropieza en el procedimiento. Según se coloque en un archivo separado o se incruste en el binario, cambia el nombre que se puede usar.
Side-by-side busca los private assembly en la carpeta de la aplicación siguiendo este orden:
- La carpeta WinSxS
<appdir>\<assemblyname>.DLL<appdir>\<assemblyname>.manifest<appdir>\<assemblyname>\<assemblyname>.DLL<appdir>\<assemblyname>\<assemblyname>.manifest
Si se encuentra antes una DLL con el mismo nombre que el assembly, la búsqueda se detiene ahí. A partir de esto, solo son válidas estas dos combinaciones.
| Forma de colocarlo | Nombre del assembly | Archivo | ID de recurso de incrustación |
|---|---|---|---|
| Archivo separado | Debe ser distinto del nombre de la DLL. Ejemplo: Vendor.CameraControl.Asm |
Vendor.CameraControl.Asm.manifest colocado junto a la DLL |
No se incrusta |
| Incrustado en la DLL | Puede ser igual que el de la DLL. Ejemplo: Vendor.CameraControl |
Solo Vendor.CameraControl.dll |
1 |
Es decir, si se usa el nombre Vendor.CameraControl.Asm como en los ejemplos de 10.2 y 10.3, esa es la convención del archivo separado. Para pasar a incrustación, hay que cambiar el name de assemblyIdentity a Vendor.CameraControl y alinear también el lado de dependentAssembly con el mismo nombre.
Hay otra restricción con la que es fácil equivocarse. El manifiesto del componente no se puede incluir como recurso del EXE. Lo que puede incluirse en el EXE es el manifiesto de la aplicación.
Para incrustarlo se usa mt.exe (la herramienta de manifiestos) del Windows SDK. Ejecútela desde el símbolo del sistema para desarrolladores de Visual Studio.
rem 1. Antes de incrustar, primero se valida la sintaxis
mt.exe -manifest MyApp.exe.manifest -validate_manifest
mt.exe -manifest Vendor.CameraControl.manifest -validate_manifest
rem 2. Incrustar el manifiesto de la aplicación en el EXE
mt.exe -manifest MyApp.exe.manifest -outputresource:MyApp.exe;#1
rem 3. Incrustar el manifiesto del componente en la DLL (el ID de recurso es 1)
mt.exe -manifest Vendor.CameraControl.manifest -outputresource:Vendor.CameraControl.dll;#1
rem 4. Extraerlo para comprobar que quedó incrustado
mt.exe -inputresource:Vendor.CameraControl.dll;#1 -out:extracted.manifest
Si compara el extracted.manifest obtenido con el cuarto comando frente al XML original, puede descartar el error de «creía haberlo incrustado, pero no estaba».
mt.exe tiene dos puntos de cuidado:
- Los archivos referenciados por el manifiesto deben estar en el mismo directorio que el manifiesto. Si escribió
<file name="Vendor.CameraControl.dll">, coloque esa DLL junto al manifiesto antes de ejecutar el comando. Si la salida de compilación y la ubicación del manifiesto están separadas, el proceso se detiene aquí - Si se omite el ID de recurso en
-outputresource, se usaCREATEPROCESS_MANIFEST_RESOURCE(= 1). Para evitar que se convierta en 1 sin que sea intencional, es más legible dejar;#1de forma explícita
Si solo quiere reemplazar algo que ya está incrustado, puede usar -updateresource:<archivo>;#1. Esto equivale a pasar el mismo argumento tanto a -inputresource como a -outputresource.
10.5 Procedimiento de verificación, incluido un entorno limpio
Con Reg-Free COM, «funcionó en la máquina de desarrollo» prácticamente no significa nada, porque siempre queda la posibilidad de que solo se esté beneficiando de un registro local. Verifíquelo en este orden:
- Compile y reúna todo el paquete de distribución en una sola carpeta. Incluya el EXE, el manifiesto, la COM DLL, las DLL dependientes, el runtime de VC++ y las DLL de proxy / stub
- Prepare un entorno de verificación. Lo ideal es un entorno donde el COM en cuestión no se haya registrado nunca. Con Windows Sandbox puede probarlo cada vez desde un estado completamente limpio
- En ese entorno, confirme primero que el COM en cuestión no está registrado. Si el comando siguiente devuelve un error indicando que no se encuentra la clave, es que no está registrado
- Copie la carpeta e inícielo tal cual. No ejecute el instalador ni
regsvr32 - Confirme que la creación del objeto COM se completa correctamente. El mero inicio no verifica los componentes de creación diferida. Ejecute realmente la pantalla o la función en la que se llama a
CoCreateInstance - Si falla, tome los registros siguiendo el procedimiento de 11.2
El comando que se usa en el paso 3 es este:
reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:64
reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:32
reg query "HKCR\Vendor.CameraControl.1"
Las vistas de registro de 32 bits y de 64 bits son independientes, así que revise siempre la que corresponda a la bitness de la aplicación. Es más seguro comprobar tanto /reg:64 como /reg:32.
Si quiere probarlo en la máquina de desarrollo, primero quite el registro con regsvr32 /u Vendor.CameraControl.dll y verifique después. Sin embargo, en un entorno donde otro producto use el mismo COM esto puede afectarlo, así que es más seguro preparar un entorno limpio.
11. Problemas frecuentes
11.1 Funciona en la máquina de desarrollo pero no en el destino de distribución
Lo primero que hay que sospechar es que en realidad se estaba beneficiando de un registro en el registro de Windows. Es más seguro verificar Reg-Free COM, en la medida de lo posible, en un entorno limpio.
11.2 No se inicia con el error «side-by-side configuration is incorrect»
Este tipo de error se produce por inconsistencias en el manifiesto, falta de DLL dependientes, falta del runtime de VC++, diferencias de arquitectura, etc.
El texto del error por sí solo suele ser bastante poco informativo, así que lo habitual es investigarlo con el registro de eventos y con sxstrace.
Para el registro de eventos, abra el Visor de eventos > Registros de Windows > Aplicación, y busque los errores cuyo origen sea SideBySide. Ahí aparece en la resolución de qué assembly falló.
sxstrace se toma reproduciendo el fallo. Es más seguro abrir el símbolo del sistema como administrador.
rem 1. Iniciar la traza. Deje esta ventana abierta
sxstrace trace -logfile:sxstrace.etl
rem 2. En otra ventana, inicie la aplicación y reproduzca el fallo
rem 3. Detener la traza. Pulse Entrar en la ventana del paso 1, o ejecute lo siguiente desde otra ventana
sxstrace stoptrace
rem 4. Convertir el .etl sin procesar a un formato legible
sxstrace parse -logfile:sxstrace.etl -outfile:sxstrace.txt
Si no quiere que aparezca el mensaje para detener, añada -nostop en el paso 1. Si la salida es demasiado larga, añadir -filter:MyApp.exe en el paso 4 permite acotarla solo a la aplicación en cuestión.
En el sxstrace.txt resultante aparecen, en orden, qué manifiesto se buscó y en qué punto no hubo coincidencia. Incluso si se equivocó en la convención de nombres de 10.4, aquí puede verlo mirando «el nombre de archivo que se fue a buscar».
11.3 Desajuste entre el manifiesto del componente y el de la aplicación
- El name es distinto
- La version es distinta
- El processorArchitecture es distinto
- El manifiesto que creía haber copiado en realidad está desactualizado
Estas diferencias parecen mínimas a simple vista, pero tienen un efecto bastante grande en el inicio.
11.4 Olvidar colocar las DLL dependientes
Si se conforma con revisar solo Vendor.CameraControl.dll, se olvida de Vendor.Helper.dll, del runtime de VC++ y de las DLL de proxy / stub que se leen más adelante.
Reg-Free COM reduce los problemas de registro de COM, pero no hace desaparecer los problemas de resolución de dependencias nativas.
11.5 Postergar la gestión de la biblioteca de tipos y las referencias
Aunque solo se resuelva la activación en tiempo de ejecución, si se necesita:
- Enlace temprano (early binding) desde VBA
#importen C++- Generar interop en tiempo de diseño en .NET
entonces hace falta una forma de distribuir la información de tipos. Reg-Free COM no organiza todo esto de forma automática, así que es importante separar el pensamiento entre tiempo de ejecución (runtime) y tiempo de diseño (design-time).
12. Resumen
Si tuviera que resumir Reg-Free COM en una frase, sería: un mecanismo que traslada la información de registro de COM del ámbito de toda la máquina al ámbito de cada aplicación.
Esto aporta las siguientes ventajas:
- Facilita mantener la COM DLL / OCX aislada por aplicación
- Facilita reducir los conflictos de versión
- Facilita simplificar la distribución y la reversión
Por otro lado, siguen siendo importantes:
- 32 bits / 64 bits
- Las DLL dependientes
- El TLB / la configuración de referencias
- Las dependencias de registro no estándar
- La verificación en un entorno limpio
Por eso, la actitud básica al introducir Reg-Free COM es esta:
- Asumir que esto es una cuestión de activación
- Separar los puntos de runtime y de design-time
- Verificarlo en un entorno limpio
- Alinear primero la bitness y las DLL dependientes
Si lo aborda en este orden, el riesgo de incidentes se reduce bastante.
13. Artículos relacionados
- ¿Qué es COM / ActiveX / OCX? - Diferencias y relación explicadas
- Cómo tratar ActiveX / OCX hoy - Tabla de decisión: mantener, envolver o reemplazar
- Cómo usar una DLL de .NET 8 desde VBA de forma tipada - Exposición COM y TLB con dscom
14. Referencias
- Microsoft Learn - Creación de objetos COM sin registro (Registration-Free COM)
- Microsoft Learn - Manifiestos de aplicación
- Microsoft Learn - Assembly Manifests (restricciones de ID de recurso y de nombre al incrustar)
- Microsoft Learn - Assembly Searching Sequence (orden de búsqueda de private assembly)
- Microsoft Learn - Manifest File Schema
- Microsoft Learn - Mt.exe
- Microsoft Learn - Interoperabilidad COM sin necesidad de registro (.NET Framework)
- Microsoft Learn - Exposición de componentes de .NET Core a COM
- Microsoft Learn - sxstrace
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
Qué son COM, ActiveX y OCX - Diferencias y relación explicadas
Explicamos qué son COM, ActiveX y OCX: diferencias, relación, vínculo con OLE, dónde se usan y cómo abordarlos hoy desde una perspectiva ...
Cómo funcionan el portapapeles y arrastrar y soltar — Gestionar correctamente la transferencia de datos OLE en aplicaciones empresariales
Una tabla de Excel se deforma al pegarla y deja de poder pegarse si cierra el origen: es el portapapeles colocando el mismo contenido en ...
Trampas de registro y bitness en el desarrollo COM/OCX/ActiveX
Un repaso práctico de los problemas más comunes en COM, OCX y ActiveX: bitness de 32/64 bits, Visual Studio 2022, regsvr32/Regasm, permis...
Introducción a Media Foundation - Cómo entender la API desde la perspectiva de COM
Explicamos qué es Media Foundation junto con los términos básicos de su API multimedia en Windows —COM, HRESULT, IMFSourceReader, MFT— en...
Conocimientos básicos de STA/MTA en COM - El modelo de subprocesos y cómo evitar los bloqueos
Explicamos los fundamentos de STA/MTA en COM: el Apartment Model, el subproceso de UI, el bucle de mensajes, la marshalling y cómo evitar...
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
Es un tema directamente relacionado con la implementación de aplicaciones de escritorio Windows, que abarca la distribución de COM DLL / OCX, la configuración de manifiestos, la bitness y las DLL dependientes.
Consultoría técnica y revisión de diseño
También es útil para organizar la decisión de si conviene adoptar Reg-Free COM o mantener una operación basada en registro, y cómo separar las bibliotecas de tipos y las referencias en tiempo de diseño.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Qué es Reg-Free COM?
- Es un mecanismo que mantiene la información de registro de COM en un manifiesto en lugar de en el registro de Windows; su nombre es la abreviatura de Registration-Free COM. En tiempo de ejecución, al resolver CoCreateInstance o CLSIDFromProgID, primero se consulta el contexto de activación, y a partir de la información del manifiesto escrita allí se resuelve la DLL correspondiente. Esto permite mantener la COM DLL / OCX de forma privada por aplicación, con ventajas como facilitar la distribución por copia directa (XCOPY), evitar más fácilmente los conflictos de versión y reducir el riesgo de que una desinstalación quede rota.
- ¿Con Reg-Free COM también se resuelve el problema de 32 bits / 64 bits?
- No se resuelve. Un proceso de 32 bits solo puede cargar una COM DLL in-proc de 32 bits, y un proceso de 64 bits solo puede cargar una DLL de 64 bits. En esto, Reg-Free se comporta igual que siempre. Además, hay que seguir considerando por separado la distribución de las DLL dependientes y del runtime de VC++, las bibliotecas de tipos, la configuración de referencias en tiempo de diseño y la dependencia de información de registro no estándar. Lo que Reg-Free COM elimina es, sobre todo, la molestia derivada del registro global.
- ¿Por qué una configuración de Reg-Free COM funciona en la máquina de desarrollo pero no en el destino de distribución?
- Lo primero que hay que sospechar es que, en realidad, se estaba beneficiando de un registro previo en el registro de Windows. Cuando falta información necesaria en el manifiesto, el runtime de COM recurre a la resolución tradicional basada en registro, por lo que en la máquina de desarrollo puede funcionar por casualidad gracias a un registro local. Por eso es más seguro verificar Reg-Free COM en un entorno limpio. Si la aplicación no se inicia con el error «side-by-side configuration is incorrect», suele deberse a inconsistencias en el manifiesto o a la falta de DLL dependientes, y lo habitual es investigarlo con el registro de eventos y sxstrace.
- ¿También se puede convertir en Reg-Free COM un componente COM creado con .NET 8?
- Sí, es posible. En .NET 5+/.NET 8, con EnableComHosting se genera el archivo *.comhost.dll que actúa como punto de entrada para la exposición COM, y si además se activa EnableRegFreeCom=true, se genera el manifiesto side-by-side para Reg-Free COM. Sin embargo, Reg-Free COM y la estrategia de TLB son cuestiones distintas. En .NET Core/.NET 5+ el TLB ya no se genera de forma natural a partir del ensamblado como ocurría en la época de .NET Framework, así que si se necesita un uso tipado, como el enlace temprano (early binding) desde VBA, es más seguro organizar por separado la generación, incrustación y registro del TLB.
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.