Inheritance: System.MarshalByRefObject
        static void Main(string[] args)
        {
            try
            {
                var localObject = new RemoteObject();
                Console.WriteLine("Local object - Main Module Location: {0}", localObject.GetProcessMainModuleFileName());
                Console.WriteLine("Local object - App.config location: {0}", localObject.GetAppConfigLocation());
                Console.WriteLine("Local object - App.config value: {0}", localObject.GetAppConfigValue("MyString"));

                var setup = new ProcessDomainSetup
                {
                    ProcessStartTimeout = new TimeSpan(0, 0, 5),
                };

                using (ProcessDomain processDomain = ProcessDomain.CreateDomain("RemoteProcess", setup))
                {
                    LoggingConfigurator.CreateConfigurator(processDomain).ConfigureAppConfig();

                    var remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                    Console.WriteLine("Remote object - Main Module Location: {0}", remoteObject.GetProcessMainModuleFileName());
                    Console.WriteLine("Remote object - App.config location: {0}", remoteObject.GetAppConfigLocation());
                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));

                    var detachedEvent = new ManualResetEvent(false);
                    var attachedEvent = new ManualResetEvent(false);
                    processDomain.Detached += () => detachedEvent.Set();
                    processDomain.Attached += () =>
                    {
                        LoggingConfigurator.CreateConfigurator(processDomain).ConfigureAppConfig();
                        attachedEvent.Set();
                    };

                    Console.WriteLine("Finding RemoteProcess and killing it...");
                    Process.GetProcessesByName("RemoteProcess").FirstOrDefault().Kill();

                    if (!detachedEvent.WaitOne(10000))
                    {
                        throw new Exception("Timed-out while waiting for process to die");
                    }

                    Console.WriteLine("Waiting for new process to spawn");
                    if (!attachedEvent.WaitOne(10000))
                    {
                        throw new Exception("Timed-out while waiting for process to restart");
                    }

                    Console.WriteLine("Re-creating remote object in newly spawned process");
                    remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                    Console.WriteLine("Remote object - Main Module Location: {0}", remoteObject.GetProcessMainModuleFileName());
                    Console.WriteLine("Remote object - App.config location: {0}", remoteObject.GetAppConfigLocation());
                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));

                    Console.WriteLine("Throwing an exception...");
                    try
                    {
                        remoteObject.ThrowException();
                        Console.WriteLine("Did not catch an exception...");
                    }
                    catch (RemoteException rex)
                    {
                        Console.WriteLine("Caught exception: {0}", rex.Message);
                    }
                }

                Console.WriteLine("Two process domains at the same time");

                using (var processDomain1 = ProcessDomain.CreateDomain("RemoteProcess1", setup))
                using (var processDomain2 = ProcessDomain.CreateDomain("RemoteProcess2", setup))
                {
                    var remoteObject1 = (RemoteObject)processDomain1.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                    var remoteObject2 = (RemoteObject)processDomain2.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);

                    Console.WriteLine("Remote object #1 - App.config value: {0}", remoteObject1.GetAppConfigValue("MyString"));
                    Console.WriteLine("Remote object #2 - App.config value: {0}", remoteObject2.GetAppConfigValue("MyString"));
                }

                Console.WriteLine("Process domain in alternate location");
                setup.AppDomainSetupInformation.ApplicationBase = @"c:\";
                setup.ExternalAssemblies[typeof(Program).Assembly.GetName()] = typeof(Program).Assembly.Location;
                using (var processDomain = ProcessDomain.CreateDomain("RemoteProcess", setup))
                {
                    var remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);

                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            try
            {
                var localObject = new RemoteObject();
                Console.WriteLine("Local object - Main Module Location: {0}", localObject.GetProcessMainModuleFileName());
                Console.WriteLine("Local object - App.config location: {0}", localObject.GetAppConfigLocation());
                Console.WriteLine("Local object - App.config value: {0}", localObject.GetAppConfigValue("MyString"));

                var setup = new ProcessDomainSetup
                {
                    ProcessStartTimeout = new TimeSpan(0, 0, 5),
                };

                using (ProcessDomain processDomain = ProcessDomain.CreateDomain("RemoteProcess", setup))
                {
                    LoggingConfigurator.CreateConfigurator(processDomain).ConfigureAppConfig();

                    var remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                    Console.WriteLine("Remote object - Main Module Location: {0}", remoteObject.GetProcessMainModuleFileName());
                    Console.WriteLine("Remote object - App.config location: {0}", remoteObject.GetAppConfigLocation());
                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));

                    var detachedEvent = new ManualResetEvent(false);
                    var attachedEvent = new ManualResetEvent(false);
                    processDomain.Detached += () => detachedEvent.Set();
                    processDomain.Attached += () =>
                    {
                        LoggingConfigurator.CreateConfigurator(processDomain).ConfigureAppConfig();
                        attachedEvent.Set();
                    };

                    Console.WriteLine("Finding RemoteProcess and killing it...");
                    Process.GetProcessesByName("RemoteProcess").FirstOrDefault().Kill();

                    if (!detachedEvent.WaitOne(10000))
                    {
                        throw new Exception("Timed-out while waiting for process to die");
                    }

                    Console.WriteLine("Waiting for new process to spawn");
                    if (!attachedEvent.WaitOne(10000))
                    {
                        throw new Exception("Timed-out while waiting for process to restart");
                    }

                    Console.WriteLine("Re-creating remote object in newly spawned process");
                    remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                    Console.WriteLine("Remote object - Main Module Location: {0}", remoteObject.GetProcessMainModuleFileName());
                    Console.WriteLine("Remote object - App.config location: {0}", remoteObject.GetAppConfigLocation());
                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));

                    Console.WriteLine("Throwing an exception...");
                    try
                    {
                        remoteObject.ThrowException();
                        Console.WriteLine("Did not catch an exception...");
                    }
                    catch (RemoteException rex)
                    {
                        Console.WriteLine("Caught exception: {0}", rex.Message);
                    }
                }

                Console.WriteLine("Two process domains at the same time");

                using (var processDomain1 = ProcessDomain.CreateDomain("RemoteProcess1", setup))
                    using (var processDomain2 = ProcessDomain.CreateDomain("RemoteProcess2", setup))
                    {
                        var remoteObject1 = (RemoteObject)processDomain1.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);
                        var remoteObject2 = (RemoteObject)processDomain2.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);

                        Console.WriteLine("Remote object #1 - App.config value: {0}", remoteObject1.GetAppConfigValue("MyString"));
                        Console.WriteLine("Remote object #2 - App.config value: {0}", remoteObject2.GetAppConfigValue("MyString"));
                    }

                Console.WriteLine("Process domain in alternate location");
                setup.AppDomainSetupInformation.ApplicationBase = @"c:\";
                setup.ExternalAssemblies[typeof(Program).Assembly.GetName()] = typeof(Program).Assembly.Location;
                using (var processDomain = ProcessDomain.CreateDomain("RemoteProcess", setup))
                {
                    var remoteObject = (RemoteObject)processDomain.CreateInstanceAndUnwrap(typeof(RemoteObject).Assembly.FullName, typeof(RemoteObject).FullName);

                    Console.WriteLine("Remote object - App.config value: {0}", remoteObject.GetAppConfigValue("MyString"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }