dynamic assembly

Best Practices for Assembly Loading for portable applications

Some of you have certainly met with many different aspects of developing applications based on extensions. The following publication raises the question of practices for extensions in portable applications.

On msdn pages you will find well designed in theory and with almost identical title as ours: Best Practices for Assembly Loading . In short - we get a knowledge of the 'pros and cons' of different approaches and although unfortunately article lacks of practical examples it is worth to get familiar with it.
 

Running executable from MemoryStream / Resources / binary array

Be aware, that executables or assemblies loaded in such manner share main application (host) domain. This implies that if there is any reference needed other from GAC (GlobalAssemblyCache) or host working directory - you will need to handle AppDomain.CurrentDomain.AssemblyResolve event or create new AppDomain for example. Sample code:
using System;
using System.IO;
using System.Reflection;
 
namespace ExecutableMemoryStream
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0)
                    throw new TargetParameterCountException(
                             "Expected at least one parameter containing executable path.");
 
                using (FileStream fileStream = new FileStream(args[0], FileMode.Open))
                using (BinaryReader reader = new BinaryReader(fileStream))
                {
                    byte[] bin = reader.ReadBytes(Convert.ToInt32(fileStream.Length));
                    Assembly assembly = Assembly.Load(bin);
                    MethodInfo method = assembly.EntryPoint;
                    if (method != null)
                    {
                        object o = assembly.CreateInstance(method.ReflectedType.Name);
                        if (method.GetParameters().Length == 0)
                            method.Invoke(o, new object[0]);
                        else
                        {
                            string[] parameters = new string[args.Length - 1];
                            for (int i = 1; i < args.Length; i++)
                                parameters[i - 1] = args[i];
                            method.Invoke(o, new[] { parameters });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.BackgroundColor = ConsoleColor.Red;
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine();
                Console.WriteLine(ex.Message.PadRight(80));
                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Hit 'd' for details. Any other key will terminate application.");
                if (Console.ReadKey(true).KeyChar == 'd')
                {
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.WriteLine();
                    Console.WriteLine(ex.StackTrace);
                    Console.ReadKey();
                }
            }
        }
    }
}
Syndicate content