Compartir a través de


Registration-Free Activation of .NET-Based Components: A Walkthrough (Tutorial: Activación sin registro de componentes basados en .NET)

 

Steve White
Soporte técnico Premier para desarrolladores, Microsoft UK

Leslie Muller
Desarrollo de investigación de & TI global, Credit Suisse First Boston

Julio de 2005

Resumen: Microsoft Platform SDK realiza un excelente trabajo para documentar los temas de aplicaciones aisladas y ensamblados en paralelo. Sin embargo, no todos equivalen a este tema con el de la activación sin registro de componentes COM. COM sin registro es una característica de plataforma de gran interés para las empresas con servidores bloqueados y aplicaciones aisladas en infraestructuras compartidas. En este artículo se explica un ejemplo de trabajo de la activación sin registro de un componente basado en .NET Framework por parte de clientes nativos a través de la interoperabilidad COM. (11 páginas impresas)

Se aplica a:
   Microsoft Windows Server 2003
   Microsoft Windows XP Service Pack 2
   Microsoft .NET Framework versión 1.1
   Microsoft Visual Studio .NET 2003
   Microsoft Visual Basic 6.0

Descargue el ejemplo que acompaña a este artículo, MSDNRegFreeNet.msi.

Contents

Introducción
terminología com de Registration-Free
Ejecutar el ejemplo
Creación de un ensamblado de .NET como servidor COM
Compilación del cliente
Activación de Registration-Free
Solución de problemas
Conclusión
Lecturas adicionales

Introducción

COM sin registro es un mecanismo disponible en las plataformas Microsoft Windows XP (SP2 para componentes basados en .NET Framework) y Microsoft Windows Server 2003. Como sugiere el nombre, el mecanismo permite una implementación sencilla (por ejemplo, XCOPY) de componentes COM en una máquina sin necesidad de registrarlos.

En las plataformas de destino, una de las fases de inicialización de un proceso y sus módulos dependientes consiste en cargar los archivos de manifiesto asociados en una estructura de memoria denominada contexto de activación. En ausencia de las entradas del Registro correspondientes, es un contexto de activación que proporciona la información de enlace y activación que necesita el entorno de ejecución COM. No se requiere ningún código especial en el servidor COM o en el cliente, a menos que decida obviar el uso de archivos mediante la creación de contextos de activación usted mismo mediante la API de contexto de activación.

En este tutorial, crearé un ensamblado .NET simple y lo consumiré, tanto registrados como no registrados, de clientes COM nativos escritos en Visual C++ y Visual Basic 6.0. Puede descargar el código fuente y los ejemplos y verlos en acción inmediatamente o puede seguir el tutorial y compilarlos paso a paso.

terminología com de Registration-Free

Cualquier persona familiar con la tecnología .NET estará acostumbrada al término ensamblado , lo que significa un conjunto de uno o varios módulos implementados, denominados y con versiones como una unidad, con un módulo que contiene un manifiesto que define el conjunto. En COM sin registro, los términos ensamblado y manifiesto se toman prestados para ideas similares en concepto, pero no idénticas a sus homólogos de .NET.

COM sin registro usa ensamblado para significar un conjunto de uno o varios módulos PE (es decir, nativos o administrados) implementados, con nombre y con versiones como una unidad. COM sin registro usa el manifiesto para hacer referencia a archivos de texto con la extensión .manifest que contiene XML, que define la identidad de un ensamblado (manifiesto de ensamblado ) junto con los detalles de enlace y activación de sus clases, o define la identidad de una aplicación (manifiesto de aplicación) junto con una o varias referencias de identidad de ensamblado. Un archivo de manifiesto de ensamblado se denomina para el ensamblado y un archivo de manifiesto de aplicación se denomina para la aplicación.

El término ensamblados en paralelo (SxS) hace referencia a la configuración de diferentes versiones del mismo componente COM, a través de archivos de manifiesto, para que se puedan cargar simultáneamente por diferentes subprocesos sin necesidad de registrarse. SxS permite, y es sinónimo flexible de COM sin registro.

Ejecutar el ejemplo

Después de descargar y extraer el código de ejemplo, encontrará una carpeta denominada \deployed. Aquí está la versión de Visual C++ de la aplicación cliente (client.exe), su manifiesto (client.exe.manifest) y la versión de C# del servidor COM (SideBySide.dll). Continúe y ejecute client.exe. El resultado esperado es que client.exe activará una instancia de SideBySideClass (implementada en SideBySide.dll) y mostrará el resultado de llamar a su método Version que debería ser similar a "1.0.0-C#".

Creación de un ensamblado de .NET como servidor COM

Paso 1

En Visual Studio .NET 2003 , cree un nuevo proyecto de biblioteca de clases .NET de C# o Visual Basic y llámelo SideBySide. Quite AssemblyInfo.[ Archivo cs/vb] del proyecto e implementa una clase de la siguiente manera:

código de C#

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("[LIBID_SideBySide]")]

namespace SideBySide
{
   [Guid("[IID_ISideBySideClass]")]
   public interface ISideBySideClass
   {
      string Version();
   }

   [Guid("[CLSID_SideBySideClass]")]
   public class SideBySideClass : ISideBySideClass
   {
      public string Version()
      {
         return "1.0.0-C#";
      }
   }
}

Código de .NET de Visual Basic

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

<Assembly: AssemblyVersion("1.0.0.0")> 
<Assembly: Guid("[LIBID_SideBySide]")>

<Guid("[IID_ISideBySideClass]")> _
Public Interface ISideBySideClass
    Function Version() As String
End Interface

<Guid("[CLSID_SideBySideClass]")> _
Public Class SideBySideClass
    Implements ISideBySideClass
    Function Version() As String Implements ISideBySideClass.Version
        Version = "1.0.0-VB.NET"
    End Function
End Class

He escrito los valores GUID, que serán específicos de su proyecto, en forma de marcadores de posición. Tendrás que usar la herramienta guidgen para generar GUID únicos que sean los valores respectivos que voy a intentar cuando después use los marcadores de posición.

Paso 2

Para que se genere y registre una biblioteca de tipos en tiempo de compilación, establezca el valor Register for COM Interop (Registrar para interoperabilidad COM ) en true.

Paso 3

Genere una compilación de versión y copie SideBySide.dll en \deployed.

Compilación del cliente

El siguiente paso es compilar el cliente y, para este tutorial, tiene la opción de compilar un cliente de Visual C++ o de Visual Basic 6.0 .

Paso 4 (opción A: Visual C++)

Cree un nuevo proyecto de consola Win32 de Visual C++ llamado cliente en una carpeta del mismo nivel relativa a la carpeta del proyecto SideBySide . En el Asistente para aplicaciones Win32, en la pestaña Configuración de la aplicación , active la casilla Agregar compatibilidad con ATL .

Edite stdafx.h y agregue la línea siguiente en la parte superior del archivo, inmediatamente después de #pragma once:

#define _WIN32_DCOM

También en stdafx.h agregue la siguiente línea en la parte inferior del archivo:

import "[path]\SideBySide.tlb" no_namespace

Aquí, [path] debe ser la ruta de acceso relativa a la biblioteca de tipos que se generó al compilar el ensamblado SideBySide . Esta ruta de acceso suele variar en función de si ha elegido un proyecto de .NET de C# o visual Basic en el paso 1.

Reemplace el contenido de client.cpp por este código:

#include "stdafx.h"
#include <iostream>
using namespace std;

void ErrorDescription(HRESULT hr)
{
    TCHAR* szErrMsg;
    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
      FORMAT_MESSAGE_FROM_SYSTEM, 
      NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
      (LPTSTR)&szErrMsg, 0, NULL) != 0)
   {
        cout << szErrMsg << endl;
        LocalFree(szErrMsg);
    }
   else
        cout << "Could not find a description for error 0x" 
           << hex << hr << dec << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
   CoInitializeEx(0, COINIT_MULTITHREADED);

   {
      ISideBySideClassPtr ptr;
      HRESULT hr = 
              ptr.CreateInstance(__uuidof(SideBySideClass));
      if (SUCCEEDED(hr))
      {
         cout << ptr->Version() << endl;
      }
      ErrorDescription(hr);

      char c;
      cin >> c;
   }

   CoUninitialize();

   return 0;
}

Genere una compilación de versión y copie \release\client.exe en \deployed.

Paso 4 (Opción B: Visual Basic 6.0)

Cree un nuevo proyecto EXE estándar de Visual Basic 6.0 . En el Explorador de proyectos , seleccione el nodo Project1 y, en la ventana Propiedades, cambie su nombre al cliente. Elegir archivo | Guarde Project As y guarde el archivo de formulario y el archivo del proyecto en una carpeta relacionada con la carpeta del proyecto SideBySide . Elegir proyecto | Referencias, active la casilla situada junto a SideBySide y elija Aceptar.

Haga doble clic en el formulario principal en el diseñador de formularios y pegue el código siguiente dentro de Sub Form_Load():

    Dim obj As New SideBySideClass
    Dim isxs As SideBySide.ISideBySideClass
    Set isxs = obj
    MsgBox isxs.Version()

Elegir archivo | Hacer client.exe... y vaya a la carpeta \deployed y, a continuación, elija Aceptar.

Paso 5

En la actualidad, la carpeta \deployed debe contener, aparte de algunos archivos intermedios, solo client.exe y SideBySide.dll; y este último habrá sido registrado por su proceso de compilación. Para comprobar que el servidor y el cliente funcionan juntos en estas circunstancias normales, ejecute \deployed\client.exe y anote la salida esperada "1.0.0-C#" o "1.0.0-VB.NET".

Paso 6

Este tutorial trata sobre com sin registro , por lo que ahora es necesario anular el registro del ensamblado SideBySide . En un símbolo del sistema de Visual Studio 2003, vaya a la carpeta \deployed y ejecute el comando : regasm /u SideBySide.dll.

Paso 7

Para ver qué efecto ha tenido el paso anterior, vuelva a ejecutar \deployed\client.exe y verá el mensaje "Clase no registrada" o "Error en tiempo de ejecución '429': el componente ActiveX no puede crear objeto". En esta fase hemos frustrado el tiempo de ejecución com de encontrar la información que necesita en el registro, pero aún tenemos que hacer que la información esté disponible por medios alternativos. Lo solucionaremos en los pasos siguientes.

Activación de Registration-Free

Paso 8

En la carpeta \deployed , cree un archivo de manifiesto de aplicación (un archivo de texto) para la aplicación client.exe y llámelo client.exe.manifest. Pegue lo siguiente en el archivo:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
   manifestVersion="1.0">
<assemblyIdentity
            type = "win32"
            name = "client"
            version = "1.0.0.0" />
<dependency>
            <dependentAssembly>
                        <assemblyIdentity
                                    type="win32"
                                    name="SideBySide"
                                    version="1.0.0.0" />
            </dependentAssembly>
</dependency>
</assembly>

Paso 9:

En la carpeta del proyecto SideBySide , cree un archivo de manifiesto de ensamblado privado (un archivo de texto) y llámelo SideBySide.manifest. Pegue lo siguiente en el archivo:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name=" SideBySide"
            version="1.0.0.0" />
<clrClass
            clsid="{[CLSID_SideBySideClass]}"
            progid="SideBySide.SideBySide"
            threadingModel="Both"
            name="SideBySide.SideBySideClass" >
</clrClass>
</assembly>

La siguiente tarea consiste en insertar el archivo de manifiesto del ensamblado anterior en el ensamblado SideBySide como un recurso win32. En el momento de escribirlo, esto es obligatorio para Windows XP, pero no para Windows Server 2003. En Windows Server 2003 puedes salir con simplemente implementar el archivo de manifiesto del ensamblado junto con el ensamblado. Sin embargo, insto a que no dependa de este comportamiento, ya que puede cambiar bien en un próximo Service Pack de Windows Server 2003. Para asegurarse de seguir admitiendo ambas plataformas en el futuro, siga los pasos siguientes e inserte el archivo de manifiesto del ensamblado en el ensamblado de .NET como un recurso win32. Esto solo es necesario para la activación sin registro de . Los componentes basados en NET y no son un requisito para la activación sin registro de componentes COM nativos .

Paso 10

En la carpeta del proyecto SideBySide , cree un archivo de script de definición de recursos (un archivo de texto) y llámelo SideBySide.rc. Pegue lo siguiente en el archivo:

#include <windows.h>
#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID RT_MANIFEST SideBySide.manifest

El archivo windows.h y sus dependencias están disponibles al instalar el SDK de plataforma (sección SDK principal) o Visual C++. La parte de windows.h que se requiere aquí es la definición:

#define RT_MANIFEST 24

Por lo tanto, el contenido de SideBySide.rc se resuelve en:

1 24 SideBySide.manifest

Sin embargo, es más claro y más general usar las definiciones de macro como se indica.

Paso 11

En la carpeta del proyecto SideBySide , cree un archivo de comandos de compilación (un archivo de texto) y llámelo build.cmd. Pegue lo siguiente en el archivo:

Para compilar C#:

rc SideBySide.rc
csc /t:library /out:..\deployed\SideBySide.dll 
/win32res:SideBySide.res Class1.cs

Para compilar Visual Basic .NET:

rc SideBySide.rc
vbc /t:library /out:..\deployed\SideBySide.dll 
/win32resource:SideBySide.res /rootnamespace:SideBySide Class1.vb

Lo que hacen estos comandos es primero invocar la herramienta compilador de recursos de Microsoft Windows desde platform SDK (rc.exe) para compilar el script de definición de recursos del paso 10 en un archivo de recursos compilado denominado SideBySide.res. A continuación, invoca el compilador de .NET de C# o Visual Basic para compilar el archivo de código fuente en un ensamblado e insertar el archivo de recursos compilado en él como un recurso win32. El ensamblado compilado se escribe en la carpeta \implementado , pero no está registrado para la interoperabilidad COM.

Paso 12

En un símbolo del sistema de Visual Studio 2003, vaya a la carpeta del proyecto SideBySide y ejecute el comando : build.

Paso 13

Para comprobar que, cortesía de los archivos de manifiesto, el cliente puede activar una vez más la clase SideBySideClass a través de la interoperabilidad COM, ejecutar \deployed\client.exe y anotar la salida esperada "1.0.0-C#" o "1.0.0-VB.NET".

Solución de problemas

Como hemos visto, la activación sin registro de componentes basados en .NET Framework no requiere código especial en el servidor ni en el cliente. Todo lo necesario es un par coincidente de archivos de manifiesto, uno de los cuales se inserta en el ensamblado de .NET como un recurso win32 de tipo RT_MANIFEST.

Sugiero que se acerque a su propio desarrollo sin registro como lo hace este tutorial. En concreto: primero llegue a un estado conocido viendo que el cliente trabaja con un servidor registrado; a continuación, anule el registro del servidor y confirme que el mensaje de error es lo que esperaba; y, por último, solucionar la situación mediante la creación e implementación de archivos de manifiesto. De este modo, los esfuerzos de solución de problemas relacionados con la activación sin registro se limitarán a la estructura de los archivos de manifiesto y a la inserción correcta del manifiesto del ensamblado.

Al solucionar problemas de COM sin registro, el Visor de eventos en Windows Server 2003 es su amigo. Cuando Windows XP o Windows Server 2003 detectan un error de configuración, normalmente mostrará un cuadro de mensaje de error titulado para la aplicación que ha iniciado y que contiene el mensaje "No se pudo iniciar esta aplicación porque la configuración de la aplicación es incorrecta. La reinstalación de la aplicación puede solucionar este problema". Se recomienda que, cada vez que vea este mensaje, reproduzca el problema en Windows Server 2003, consulte el registro de eventos del sistema y busque eventos del origen SideBySide . La razón por la que no sugiero que examine el registro de eventos de XP en estos casos es que contendrá invariablemente un mensaje como "Error de generar contexto de activación para [ruta]\[nombre de archivo de la aplicación]. Manifiesto. Mensaje de error de referencia: la operación se completó correctamente", que no ayuda a identificar el problema.

Antes de pasar a la estructura de los archivos de manifiesto, vamos a hablar sobre los recursos de Win32. Como se mencionó anteriormente, windows.h define el símbolo RT_MANIFEST como el valor 24, que es el valor que el sistema operativo reconocerá como un archivo de manifiesto incrustado. Si olvida incluir windows.h en el script de definición de recursos (archivo .rc), la compilación seguirá siendo correcta y el archivo de manifiesto seguirá insertado como un recurso, pero no del tipo correcto. Para comprobar que ha insertado correctamente su manifiesto, abra elSideBySide.dll en Visual Studio (Archivo | Abrir | Archivo...). Verá una vista de árbol en la que se muestran los recursos dentro del módulo. En el nodo raíz debe ser un nodo denominado RT_MANIFEST debajo, que debe ser otro nodo que muestre el número de recurso del recurso de manifiesto (1 en el tutorial). Haga doble clic en este último nodo para ver los datos en una vista binaria y darle una comprobación rápida de integridad de que se parezca al archivo de manifiesto XML. Aunque es binario, los caracteres del intervalo ASCII serán obvios. Si faltan datos binarios o parece incorrecto, compruebe que el script de definición de recursos (archivo .rc) hace referencia al archivo de manifiesto. Si el texto del nodo RT_MANIFEST está entre comillas, es probable que haya olvidado incluir windows.h en el script de definición de recursos (archivo .rc).

Cada uno de los errores mencionados se notificará en el registro de eventos del sistema de Windows Server 2003 con el mensaje: "No se encontró el ensamblado dependiente [nombre] y último error fue el ensamblado al que se hace referencia no está instalado en el sistema".

Los esquemas de los distintos archivos de manifiesto se documentan en platform SDK bajo el encabezado Referencia de archivos de manifiesto y la herramienta de validación de esquemasManifestchk.vbs está disponible, por lo que aquí solo llamaré algunos puntos relevantes para el tutorial. En primer lugar, vamos a examinar el archivo de manifiesto del ensamblado. Para obtener un ejemplo, vuelva al paso 9.

Recordará que, en el sentido COM sin registro , un ensamblado es una idea abstracta con la que asocia uno o varios archivos físicos mediante el contenido del archivo de manifiesto del ensamblado .

El elemento assemblyIdentity define la identidad del ensamblado. Para. Los componentes basados en NET que su atributo name debe coincidir con el nombre del ensamblado de .NET y, por tanto, su nombre de archivo; de lo contrario, verá el siguiente mensaje en el registro de eventos del sistema de Windows Server 2003: "No se encontró el ensamblado dependiente [valor del atributo name ] y El último error fue El ensamblado al que se hace referencia no está instalado en el sistema". Sin embargo, el atributo de versión no necesita coincidir con assemblyVersion del ensamblado de .NET ni con assemblyFileVersion, aunque es una buena idea aplicar algún tipo de coherencia.

El elemento clrClass solo tiene dos atributos obligatorios: name y clsid. El atributo namedebe coincidir con el espacio de nombres combinado y el nombre de clase de la clase CLR que se está activando. Si no es así, CoCreateInstance devolverá un VALOR HRESULT con el valor COR_E_TYPELOAD (0x80131522). Esto se debe a que se produce una excepción System.TypeLoadException cuando el cargador de tipos no encuentra el tipo CLR solicitado en el ensamblado de .NET. Algo que se debe watch para si el ensamblado de .NET está escrito en Visual Basic .NET es que está proporcionando el modificador /rootnamespace en la línea de comandos al compilador de .NET de Visual Basic (vbc.exe). El atributo clsiddebe coincidir con el CLSID asignado a la clase CLR que se activa a través de su GuidAttribute. Si no es así, CoCreateInstance devolverá un VALOR HRESULT con el valor REGDB_E_CLASSNOTREG (0x80040154), el texto del mensaje para el que es "Clase no registrada".

Ahora vamos a llamar nuestra atención al archivo de manifiesto de aplicación. Para obtener un ejemplo, vuelva al paso 8. El manifiesto de aplicación debe tener el nombre [nombre de archivo de la aplicación].manifest. Por lo tanto, en el tutorial se llamó client.exe.manifest para que quede claro que debe leerse cada vez que se cargaclient.exe en un proceso. Si esto no se hace correctamente, CoCreateInstance devolverá un HRESULT con el valor REGDB_E_CLASSNOTREG (0x80040154), el texto del mensaje para el que es "Clase no registrada".

El elemento más importante del manifiesto de aplicación es el elementoassemblyIdentitydependienteAssembly/. Este elemento es una referencia al equivalente del manifiesto del ensamblado y los dos tienen que coincidir exactamente. Una buena manera de asegurarse de que lo hacen es copiar el elemento del manifiesto del ensamblado y pegarlo aquí. Si hay alguna diferencia, verá el siguiente mensaje en el registro de eventos del sistema de Windows Server 2003: "La identidad del componente encontrada en el manifiesto no coincide con la identidad del componente solicitado".

Conclusión

COM sin registro es una tecnología que libera los componentes COM de una dependencia en el Registro de Windows y, por tanto, libera las aplicaciones que las usan de requerir servidores dedicados. Permite que las aplicaciones con dependencias en diferentes versiones del mismo componente COM compartan una infraestructura y carguen esas distintas versiones de componentes COM en paralelo en un eco del mecanismo de implementación y control de versiones de .NET.

Este artículo le guiará a través de una demostración de la activación sin registro de los componentes basados en .NET Framework por aplicaciones cliente nativas escritas en Visual C++ y Visual Basic 6.0. Se han explicado algunos de cómo funciona el mecanismo y se subrayan algunos posibles errores de configuración y cómo solucionarlos.

Lecturas adicionales

 

Acerca del autor

Steve White es un consultor de desarrollo de aplicaciones que trabaja en el equipo de soporte técnico Premier para desarrolladores de Microsoft Reino Unido. Admite el desarrollo de clientes con Visual C#, Windows Forms y ASP.NET. Su blog tiene más información sobre sus intereses en la música, las visualizaciones y la programación.

Leslie Muller es un tecnólogo con el equipo de desarrollo de investigación & en Credit Suisse First Boston. Leslie tiene 12 años de experiencia como desarrollador y arquitecto técnico, trabajando en entornos como servicios financieros, startups tecnológicas, automatización industrial y defensa. Cuando no está programando o haciendo investigación, disfruta de esquí, hockey sobre hielo y cuando es posible haciendo cosas ligeramente locas con vehículos motorizados en entornos extremos como Islandia o las Rocas.