Incrustación de aplicaciones con System.AppDomain

Con C#, y gracias a System.AppDomain extender la funcionalidad de una aplicación mediante plugins es un juego de niños. Una forma un tanto bruta de hacerlo, es considerar que los plugins son programas externos que ejecutan una serie de acciones necesarias y pueden devolver un valor (en forma de archivo en disco). Un ejemplo de este tipo de plugins lo tenemos en la implementación de los plugins para el programa de edición gráfica GIMP (Gnu Image Manipulation Program), el cual se vale de multitud de pequeños plugins en forma de programas ejecutables que se utilizan para aplicar filtros o efectos a una imagen.

En este caso, vamos a hacer un programa muy sencillo que funcione como un servidor de aplicaciones, de forma que dos o más aplicaciones se puedan lanzar simultáneamente en diferentes hilos, lo que permite aprovechar los procesadores multicore ejecutando cada aplicación en cores distintos.

Forma de uso del código: Se crean dos proyectos de consola, se copia el código fuente del servidor en uno, y el del programa ejemplo en otro. Una vez creados se generan los dos, y se copian a la carpeta raíz ( C:\ ), y se ejecuta el programa servidor. Éste incrustará dos copias del programa ejemplo, que imprime cierto número de veces su identificador de ejecución único, y se podrá observar cómo los resultados impresos por cada programa se van intercalando gracias al paralelismo de usar hilos.

Servidor (programa que incrusta otros programas en hilos):

using System;
using System.Threading;
//using System.Reflection;
namespace remoteInvoker
{
  class Program
  {
    static void Main(string[] args)
    {
      //Mostrar el AppDomain predefinido.
      string callingDomainName = Thread.GetDomain().FriendlyName;
      Console.WriteLine(”AppDomain Servidor: “+callingDomainName);
      //Invoca al creador de aplicaciones
      crearAplicacion(@”c:\appdomainExperiment.exe”);
      crearAplicacion(@”c:\appdomainExperiment.exe”);
      //Fin
      Console.WriteLine(”Server: exit”);
      Console.ReadKey(true);
    }

    /// Crea un hilo que ejecuta una aplicación
    private static void crearAplicacion(string aplicacion) {
      Aplicacion app = new Aplicacion(aplicacion);
    }
  }

  /// Incrusta un ensamblado en un hilo para ejecutarlo
  class Aplicacion {
    // Nombre (url) de la aplicación
    string appName;

    /// Constructor, crea un dominio predeterminado
    public Aplicacion(string aplicacion) {
      appName = aplicacion;
      Thread appThread = new Thread(new ThreadStart(doWork));
      appThread.Start();
    }

    /// Método de ejecución del hilo
    private void doWork(){
      //Crea un dominio de ejecución para este hilo
      AppDomain dominio = AppDomain.CreateDomain(”serverDomain”);
      //Ejecuta el ensamblado
      dominio.ExecuteAssembly(appName);
      //Descarga el Dominio
      AppDomain.Unload(dominio);
    }
  }
}

Programa de Ejemplo:

using System;
using System.Threading;
namespace appdomainExperiment
{
  class Program
  {
  static void Main()
  {
  System.Console.BackgroundColor = ConsoleColor.Blue;
  Console.WriteLine(”Hola Mundo! (Método Principal)”);

//Obtiene el identificador único de ensamblado en ejecución
  Guid k = System.Guid.NewGuid();
  for (int i = 0; i < 10; i++)   {   Console.WriteLine(k.ToString());   Thread.Sleep(10);   }   try   { //Escribe el nombre de dominio de la aplicación   Console.WriteLine(”AppDomain Cliente: ” +   System.AppDomain.CurrentDomain.DomainManager.EntryAssembly.FullName);   }   catch   {   Console.WriteLine(”AppDomain Cliente: Aplicación independiente”);   }   System.Console.BackgroundColor = ConsoleColor.Black;   }   } } [/sourcecode]