public void TestConfigurationLocation()
        {
            // by default uses our app config
            using (var domain1 = ProcessDomain.CreateDomain("Domain1", DefaultSetupInfo))
            {
                var obj = (RemoteTestObject)domain1.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetAppConfigValue("MyValue"), Is.EqualTo("MyValue"));
            }

            // now point it at a different app config
            var setupInfo = new ProcessDomainSetup
            {
                AppDomainSetupInformation =
                {
                    ConfigurationFile = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), "OtherApp.config"),
                },
                TypeFilterLevel = TypeFilterLevel.Full
            };

            using (var domain2 = ProcessDomain.CreateDomain("Domain2", setupInfo))
            {
                var obj = (RemoteTestObject)domain2.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetAppConfigValue("MyValue"), Is.EqualTo("OtherValue"));
            }
        }
        public void TestTypeFilterLevel()
        {
            // using an event handler requires type filter level Full for a remoting channel

            // by default, it's low, which will fail
            using (var domain = ProcessDomain.CreateDomain("Domain"))
            {
                Assert.Throws <SerializationException>(
                    () => { var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName); }
                    );
            }

            // now enable the remoting channel with type filter level Full
            var setup = new ProcessDomainSetup {
                TypeFilterLevel = TypeFilterLevel.Full
            };

            using (var domain = ProcessDomain.CreateDomain("Domain", setup))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);

                obj.CalledBack = false;
                Assert.That(!obj.CalledBack);
                Assert.DoesNotThrow(() => obj.CallbackEvent += obj.SetCalledBack);
                obj.OnCallback();
                Assert.That(obj.CalledBack);
            }
        }
        public void TestProcessPriority()
        {
            // Default case
            using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain", DefaultSetupInfo))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);
                Assert.That(obj.GetPriority(), Is.EqualTo(ProcessPriorityClass.Normal));
            }

            // Try each priority
            foreach (ProcessPriorityClass priority in Enum.GetValues(typeof(ProcessPriorityClass)))
            {
                var setup = new ProcessDomainSetup {
                    PriorityClass = priority, TypeFilterLevel = TypeFilterLevel.Full
                };
                using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain", setup))
                {
                    var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);

                    // If not running as administrator, we can't run as RealTime, it will become High
                    var expectedPriority = priority == ProcessPriorityClass.RealTime && !obj.RunningAsAdministrator() ? ProcessPriorityClass.High : priority;

                    Assert.That(obj.GetPriority(), Is.EqualTo(expectedPriority));
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Runs the Activator Host and blocks until the parent process exits
        /// </summary>
        public static void Run(string[] args)
        {
            // args[0] = process domain assembly path
            // args[1] = guid
            // args[2] = parent process id
            // args[3] = ProcessDomainSetup file

            if (args.Length != 4)
            {
                return;
            }

            string friendlyName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
            string guid         = args[1];
            int    processId    = int.Parse(args[2]);

            var domainSetup = ProcessDomainSetup.Deserialize(args[3]);

            var domain = AppDomain.CreateDomain(friendlyName, domainSetup.Evidence, domainSetup.AppDomainSetupInformation);

            var type = Assembly.GetEntryAssembly().GetType("AppSecInc.ProcessDomain.AssemblyResolver");

            if (type == null)
            {
                throw new TypeLoadException("Could not load type for assembly resolver");
            }

            // add ProcessDomain assembly to resolver
            if (domainSetup.ExternalAssemblies == null)
            {
                domainSetup.ExternalAssemblies = new System.Collections.Generic.Dictionary <AssemblyName, string>();
            }
            domainSetup.ExternalAssemblies[typeof(ActivatorHost).Assembly.GetName()] = typeof(ActivatorHost).Assembly.Location;

            var resolver = domain.CreateInstanceFromAndUnwrap(type.Assembly.Location,
                                                              type.FullName,
                                                              false,
                                                              BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance,
                                                              null,
                                                              new[] { domainSetup.ExternalAssemblies },
                                                              null, null, null);

            type.InvokeMember("Setup", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, resolver, null);

            var host = (ActivatorHost)domain.CreateInstanceFromAndUnwrap(typeof(ActivatorHost).Assembly.Location,
                                                                         typeof(ActivatorHost).FullName,
                                                                         false,
                                                                         BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance,
                                                                         null,
                                                                         new object[] { guid, processId, domainSetup },
                                                                         null, null, null);

            host.WaitForExit();

            type.InvokeMember("TearDown", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, resolver, null);

            // If parent process (host) finishes, the current process must end.
            Environment.Exit(0);
        }
예제 #5
0
 private static void LogProcessDomainSetup(ProcessDomainSetup setupInfo)
 {
     Logger.InfoFormat("ExecutableDirectory = {0}", setupInfo.ExecutableDirectory);
     Logger.InfoFormat("ProcessStartTimeout = {0}", setupInfo.ProcessStartTimeout);
     Logger.InfoFormat("FileDeletionTimeout = {0}", setupInfo.FileDeletionTimeout);
     Logger.InfoFormat("DeleteOnUnload = {0}", setupInfo.DeleteOnUnload);
     Logger.InfoFormat("RestartOnProcessExit = {0}", setupInfo.RestartOnProcessExit);
     Logger.InfoFormat("WorkingDirectory = {0}", setupInfo.WorkingDirectory);
 }
예제 #6
0
 private static void SetupDllDirectories(ProcessDomainSetup setup)
 {
     if (!string.IsNullOrEmpty(setup.DllDirectory))
     {
         if (!WinApi.SetDllDirectory(setup.DllDirectory))
         {
             throw new Win32Exception();
         }
     }
 }
        public static string CreateRemoteHostAssembly(string friendlyName, ProcessDomainSetup setupInfo)
        {
            if (!Directory.Exists(setupInfo.ExecutableDirectory))
            {
                Directory.CreateDirectory(setupInfo.ExecutableDirectory);
            }

            var providerOptions = new Dictionary <string, string>
            {
                { "CompilerVersion", setupInfo.CompilerVersion ?? ProcessDomainSetup.DefaultCompilerVersion }
            };

            var provider = new CSharpCodeProvider(providerOptions);

            var compilerArgs = new List <string> {
                PlatformTargetUtil.GetCompilerArgument(setupInfo.Platform)
            };

            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = true,
                GenerateInMemory   = false,
                CompilerOptions    = string.Join(" ", compilerArgs.ToArray()),
                OutputAssembly     = Path.Combine(setupInfo.ExecutableDirectory,
                                                  string.Format(AssemblyName, friendlyName))
            };

            compilerParameters.ReferencedAssemblies.AddRange(ReferencedAssemblies);

            string assemblySource = Properties.Resources.Program
                                    .Replace("${ActivatorHostTypeName}", typeof(ActivatorHost).AssemblyQualifiedName)
                                    .Replace("${ProcessDomainAssemblyName}", typeof(ActivatorHost).Assembly.FullName);

            var results = provider.CompileAssemblyFromSource(compilerParameters, assemblySource);

            if (results.Errors.HasErrors)
            {
                throw new AssemblyGeneratorCompilerException("Failed to compile assembly for process domain due to compiler errors", results.Errors);
            }

            if (results.Errors.HasWarnings)
            {
                Logger.Warn("Process domain assembly compilation returned with warnings:");
                foreach (var error in results.Errors)
                {
                    Logger.WarnFormat("Compiler Warning: {0}", error);
                }
            }
            if (setupInfo.CopyConfigurationFile)
            {
                File.Copy(setupInfo.AppDomainSetupInformation.ConfigurationFile,
                          results.PathToAssembly + ".config", true);
            }
            return(results.PathToAssembly);
        }
예제 #8
0
        /// <summary>
        /// Starts the remote process which will host an Activator
        /// </summary>
        public void Start()
        {
            CheckDisposed();
            DisposeClient();

            Logger.InfoFormat("Starting process for Process Domain '{0}'", _friendlyName);

            String processGuid = Guid.NewGuid().ToString();

            bool created;
            var  serverStartedHandle = new EventWaitHandle(false, EventResetMode.ManualReset, string.Format(ActivatorHost.EventName, processGuid), out created);

            // We set guid to a new value every time therefore this "should" never happen.
            if (!created)
            {
                throw new Exception("Event handle already existed for remote process");
            }

            string processDomainAssemblyPath = AssemblyUtils.GetFilePathFromFileUri(typeof(ActivatorProcess).Assembly.CodeBase);

            ProcessDomainSetup.Serialize(_setupInfo, _setupInfoFile);

            // args[0] = process domain assembly path
            // args[1] = guid
            // args[2] = process id
            // args[3] = ProcessDomainSetup file
            _process.StartInfo.Arguments = string.Format("\"{0}\" {1} {2} \"{3}\"", processDomainAssemblyPath, processGuid, Process.GetCurrentProcess().Id, _setupInfoFile);

            if (!_process.Start())
            {
                throw new Exception(string.Format("Failed to start process from: {0}", _process.StartInfo.FileName));
            }

            Logger.InfoFormat("Process successfully started with process id {0}", _process.Id);

            if (!serverStartedHandle.WaitOne(_setupInfo.ProcessStartTimeout))
            {
                throw new Exception("Timed-out waiting for remote process to start");
            }

            serverStartedHandle.Close();

            _processStatus         = ProcessStatus.Active;
            _process.PriorityClass = _setupInfo.PriorityClass;
            _client = new ActivatorClient(processGuid, _setupInfo);

            var tmp = Attached;

            if (tmp != null)
            {
                tmp();
            }
        }
        public static string CreateRemoteHostAssembly(string friendlyName, ProcessDomainSetup setupInfo)
        {
            if (!Directory.Exists(setupInfo.ExecutableDirectory))
            {
                Directory.CreateDirectory(setupInfo.ExecutableDirectory);
            }

            var providerOptions = new Dictionary<string,string>
                                      {
                                          { "CompilerVersion", setupInfo.CompilerVersion ?? ProcessDomainSetup.DefaultCompilerVersion }
                                      };

            var provider = new CSharpCodeProvider(providerOptions);

            var compilerArgs = new List<string> {PlatformTargetUtil.GetCompilerArgument(setupInfo.Platform)};

            var compilerParameters = new CompilerParameters
                                      {
                                          GenerateExecutable = true,
                                          GenerateInMemory = false,
                                          CompilerOptions = string.Join(" ", compilerArgs.ToArray()),
                                          OutputAssembly = Path.Combine(setupInfo.ExecutableDirectory,
                                                                        string.Format(AssemblyName, friendlyName))
                                      };

            compilerParameters.ReferencedAssemblies.AddRange(ReferencedAssemblies);

            string assemblySource = Properties.Resources.Program
                                                            .Replace("${ActivatorHostTypeName}", typeof (ActivatorHost).AssemblyQualifiedName)
                                                            .Replace("${ProcessDomainAssemblyName}", typeof(ActivatorHost).Assembly.FullName);

            var results = provider.CompileAssemblyFromSource(compilerParameters, assemblySource);

            if (results.Errors.HasErrors)
            {
                throw new AssemblyGeneratorCompilerException("Failed to compile assembly for process domain due to compiler errors", results.Errors);
            }

            if (results.Errors.HasWarnings)
            {
                Logger.Warn("Process domain assembly compilation returned with warnings:");
                foreach (var error in results.Errors)
                {
                    Logger.WarnFormat("Compiler Warning: {0}", error);
                }
            }
            if (setupInfo.CopyConfigurationFile)
            {
                File.Copy(setupInfo.AppDomainSetupInformation.ConfigurationFile,
                          results.PathToAssembly + ".config", true);
            }
            return results.PathToAssembly;
        }
        public void TestDomainAttachDetach()
        {
            var attachedEvent = new ManualResetEvent(false);
            var detachedEvent = new ManualResetEvent(false);

            using (var domain = ProcessDomain.CreateDomain("ProcessDomain", DefaultSetupInfo))
            {
                domain.Attached += () => attachedEvent.Set();
                domain.Detached += () => detachedEvent.Set();

                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(!attachedEvent.WaitOne(0));
                Assert.That(!detachedEvent.WaitOne(0));

                // restart should occur, but our current object will be invalid
                Process.GetProcessById(obj.GetProcessId()).Kill();
                Assert.That(detachedEvent.WaitOne(10000), "Timed-out waiting for process to die");
                Assert.That(attachedEvent.WaitOne(10000), "Timed-out waiting for process to respawn");
                Assert.Throws <RemotingException>(() => obj.GetProcessId());

                // create object in restarted domain
                obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessId(), Is.Not.EqualTo(Process.GetCurrentProcess().Id));
            }

            var setupInfo = new ProcessDomainSetup
            {
                RestartOnProcessExit = false,
                TypeFilterLevel      = TypeFilterLevel.Full
            };

            // now restart should not occur
            using (var domain = ProcessDomain.CreateDomain("RemoteProcess2", setupInfo))
            {
                domain.Attached += () => attachedEvent.Set();
                domain.Detached += () => detachedEvent.Set();

                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessId(), Is.Not.EqualTo(Process.GetCurrentProcess().Id));

                attachedEvent.Reset();
                detachedEvent.Reset();

                Process.GetProcessById(obj.GetProcessId()).Kill();

                Assert.That(detachedEvent.WaitOne(10000), "Timed-out waiting for process to die");
                Assert.That(!attachedEvent.WaitOne(5000), "Unexpected re-attach");
                Assert.Throws <RemotingException>(() => obj.GetProcessId());
                Assert.Throws <RemotingException>(() => obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName));
            }
        }
        public ActivatorClient(string guid, ProcessDomainSetup setup)
        {
            var serverProvider = new BinaryServerFormatterSinkProvider { TypeFilterLevel = setup.TypeFilterLevel };
            var clientProvider = new BinaryClientFormatterSinkProvider();

            var properties = new Hashtable();
            properties["portName"] = string.Format(ActivatorHost.ClientChannelName, guid);
            properties["name"] = string.Format(ActivatorHost.ClientChannelName, guid);
            setup.Remoting.ApplyClientProperties(properties);

            _channel = new IpcChannel(properties, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(_channel, false);

            _activator = (Activator)System.Activator.GetObject(typeof(Activator), string.Format("ipc://{0}/{1}", string.Format(ActivatorHost.ServerChannelName, guid), ActivatorHost.ActivatorName));
        }
        public void TestExecutableLocation()
        {
            string desiredExecutableFileName = Path.Combine(Environment.CurrentDirectory, "MyDomain.exe");

            var setupInfo = new ProcessDomainSetup
            {
                ExecutableDirectory = Environment.CurrentDirectory,
                TypeFilterLevel     = TypeFilterLevel.Full
            };

            // default uses temp directory
            using (var domain1 = ProcessDomain.CreateDomain("MyDomain", DefaultSetupInfo))
            {
                var obj = (RemoteTestObject)domain1.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.Not.EqualTo(desiredExecutableFileName));
            }

            // now using our specified location
            using (var domain2 = ProcessDomain.CreateDomain("MyDomain", setupInfo))
            {
                var obj = (RemoteTestObject)domain2.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.EqualTo(desiredExecutableFileName));
            }

            // test if file exists, it will be overwritten
            using (var writer = new StreamWriter(desiredExecutableFileName, false))
            {
                writer.WriteLine("Garbage");

                // will fail to compile because file is open
                Assert.Throws <AssemblyGeneratorCompilerException>(() => ProcessDomain.CreateDomain("MyDomain", setupInfo));

                writer.Flush();
            }

            // file is now closed, but contains garbage that can't execute,
            // but the file will get overwritten
            using (var domain3 = ProcessDomain.CreateDomain("MyDomain", setupInfo))
            {
                var obj = (RemoteTestObject)domain3.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.EqualTo(desiredExecutableFileName));
            }

            // and once we're done, file is gone
            Assert.That(!File.Exists(desiredExecutableFileName));
        }
        public ActivatorClient(string guid, ProcessDomainSetup setup)
        {
            var serverProvider = new BinaryServerFormatterSinkProvider {
                TypeFilterLevel = setup.TypeFilterLevel
            };
            var clientProvider = new BinaryClientFormatterSinkProvider();

            var properties = new Hashtable();

            properties["portName"] = string.Format(ActivatorHost.ClientChannelName, guid);
            properties["name"]     = string.Format(ActivatorHost.ClientChannelName, guid);
            setup.Remoting.ApplyClientProperties(properties);

            _channel = new IpcChannel(properties, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(_channel, false);

            _activator = (Activator)System.Activator.GetObject(typeof(Activator), string.Format("ipc://{0}/{1}", string.Format(ActivatorHost.ServerChannelName, guid), ActivatorHost.ActivatorName));
        }
        public void TestDeleteFileOnExit()
        {
            string desiredExecutableFileName = Path.Combine(Environment.CurrentDirectory, "ProcessDomain.exe");

            var setupInfo = new ProcessDomainSetup
            {
                ExecutableDirectory = Environment.CurrentDirectory,
                DeleteOnUnload      = false
            };

            ProcessDomain.Unload(ProcessDomain.CreateDomain("ProcessDomain", setupInfo));
            Assert.That(File.Exists(desiredExecutableFileName));

            setupInfo.DeleteOnUnload = true;

            ProcessDomain.Unload(ProcessDomain.CreateDomain("ProcessDomain", setupInfo));
            Assert.That(!File.Exists(desiredExecutableFileName));
        }
예제 #15
0
        public ActivatorHost(string guid, int processId, ProcessDomainSetup setup)
        {
            SetupDllDirectories(setup);
            var serverProvider = new BinaryServerFormatterSinkProvider {
                TypeFilterLevel = setup.TypeFilterLevel
            };
            var clientProvider = new BinaryClientFormatterSinkProvider();

            _process = Process.GetProcessById(processId);

            var properties = new Hashtable();

            properties["portName"]             = string.Format(ServerChannelName, guid);
            properties["name"]                 = string.Format(ServerChannelName, guid);
            properties["rejectRemoteRequests"] = true;
            setup.Remoting.ApplyServerProperties(properties);

            _channel = new IpcChannel(properties, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(_channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(Activator), ActivatorName, WellKnownObjectMode.Singleton);

            EventWaitHandle serverStartedHandle = null;

            try
            {
                bool created;
                serverStartedHandle = new EventWaitHandle(false, EventResetMode.ManualReset, string.Format(EventName, guid), out created);

                if (created)
                {
                    throw new Exception("Event handle did not exist for remote process");
                }

                serverStartedHandle.Set();
            }
            finally
            {
                if (serverStartedHandle != null)
                {
                    serverStartedHandle.Close();
                }
            }
        }
예제 #16
0
        public void TestProcessPriority()
        {
            // Default case
            using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain"))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);
                Assert.That(obj.GetPriority(), Is.EqualTo(ProcessPriorityClass.Normal));
            }

            // Try each priority
            foreach (ProcessPriorityClass priority in Enum.GetValues(typeof(ProcessPriorityClass)))
            {
                var setup = new ProcessDomainSetup {
                    PriorityClass = priority
                };
                using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain", setup))
                {
                    var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);
                    Assert.That(obj.GetPriority(), Is.EqualTo(priority));
                }
            }
        }
예제 #17
0
        public ActivatorHost(string guid, int processId, ProcessDomainSetup setup)
        {
            SetupDllDirectories(setup);
            var serverProvider = new BinaryServerFormatterSinkProvider { TypeFilterLevel = setup.TypeFilterLevel };
            var clientProvider = new BinaryClientFormatterSinkProvider();
            _process = Process.GetProcessById(processId);

            var properties = new Hashtable();
            properties["portName"] = string.Format(ServerChannelName, guid);
            properties["name"] = string.Format(ServerChannelName, guid);
            properties["rejectRemoteRequests"] = true;
            setup.Remoting.ApplyServerProperties(properties);

            _channel = new IpcChannel(properties, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(_channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(Activator), ActivatorName, WellKnownObjectMode.Singleton);

            EventWaitHandle serverStartedHandle = null;
            try
            {
                bool created;
                serverStartedHandle = new EventWaitHandle(false, EventResetMode.ManualReset, string.Format(EventName, guid), out created);

                if (created)
                {
                    throw new Exception("Event handle did not exist for remote process");
                }

                serverStartedHandle.Set();
            }
            finally
            {
                if (serverStartedHandle != null)
                {
                    serverStartedHandle.Close();
                }
            }
        }
예제 #18
0
        public ActivatorProcess(string friendlyName, ProcessDomainSetup setupInfo)
        {
            Logger.InfoFormat("Creating ActivatorProcess for Process Domain '{0}' with the following configuration:", friendlyName);
            LogProcessDomainSetup(setupInfo);

            _friendlyName = friendlyName;
            _setupInfo    = setupInfo;
            _assemblyFile = ActivatorHostAssemblyGenerator.CreateRemoteHostAssembly(friendlyName, setupInfo);
            Logger.InfoFormat("Generated Assembly: {0}", _assemblyFile);

            var startInfo = new ProcessStartInfo
            {
                FileName         = _assemblyFile,
                CreateNoWindow   = true,
                UseShellExecute  = false,
                ErrorDialog      = false,
                WorkingDirectory = _setupInfo.WorkingDirectory,
            };

            if (_setupInfo.EnvironmentVariables != null)
            {
                foreach (var kv in _setupInfo.EnvironmentVariables)
                {
                    startInfo.EnvironmentVariables[kv.Key] = kv.Value;
                }
            }

            _process = new Process
            {
                StartInfo = startInfo
            };

            _setupInfoFile = Path.Combine(setupInfo.ExecutableDirectory, string.Format(ConfigName, friendlyName));

            _process.Exited += Process_Exited;
            _process.EnableRaisingEvents = true;
        }
        public void TestConfigurationLocation()
        {
            // by default uses our app config
            using (var domain1 = ProcessDomain.CreateDomain("Domain1"))
            {
                var obj = (RemoteTestObject)domain1.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetAppConfigValue("MyValue"), Is.EqualTo("MyValue"));
            }

            // now point it at a different app config
            var setupInfo = new ProcessDomainSetup
            {
                AppDomainSetupInformation =
                {
                    ConfigurationFile = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), "OtherApp.config")
                }
            };

            using (var domain2 = ProcessDomain.CreateDomain("Domain2", setupInfo))
            {
                var obj = (RemoteTestObject)domain2.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetAppConfigValue("MyValue"), Is.EqualTo("OtherValue"));
            }
        }
        public void TestExecutableLocation()
        {
            string desiredExecutableFileName = Path.Combine(Environment.CurrentDirectory, "MyDomain.exe");

            var setupInfo = new ProcessDomainSetup
            {
                ExecutableDirectory = Environment.CurrentDirectory
            };

            // default uses temp directory
            using (var domain1 = ProcessDomain.CreateDomain("MyDomain"))
            {
                var obj = (RemoteTestObject)domain1.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.Not.EqualTo(desiredExecutableFileName));
            }

            // now using our specified location
            using (var domain2 = ProcessDomain.CreateDomain("MyDomain", setupInfo))
            {
                var obj = (RemoteTestObject)domain2.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.EqualTo(desiredExecutableFileName));
            }

            // test if file exists, it will be overwritten
            using (var writer = new StreamWriter(desiredExecutableFileName, false))
            {
                writer.WriteLine("Garbage");

                // will fail to compile because file is open
                Assert.Throws<AssemblyGeneratorCompilerException>(() => ProcessDomain.CreateDomain("MyDomain", setupInfo));

                writer.Flush();
            }

            // file is now closed, but contains garbage that can't execute,
            // but the file will get overwritten
            using (var domain3 = ProcessDomain.CreateDomain("MyDomain", setupInfo))
            {
                var obj = (RemoteTestObject)domain3.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessFileName(), Is.EqualTo(desiredExecutableFileName));
            }

            // and once we're done, file is gone
            Assert.That(!File.Exists(desiredExecutableFileName));
        }
예제 #21
0
        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();
        }
        public void TestDomainAttachDetach()
        {
            var attachedEvent = new ManualResetEvent(false);
            var detachedEvent = new ManualResetEvent(false);

            using (var domain = ProcessDomain.CreateDomain("ProcessDomain"))
            {
                domain.Attached += () => attachedEvent.Set();
                domain.Detached += () => detachedEvent.Set();

                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(!attachedEvent.WaitOne(0));
                Assert.That(!detachedEvent.WaitOne(0));

                // restart should occur, but our current object will be invalid
                Process.GetProcessById(obj.GetProcessId()).Kill();
                Assert.That(detachedEvent.WaitOne(10000), "Timed-out waiting for process to die");
                Assert.That(attachedEvent.WaitOne(10000), "Timed-out waiting for process to respawn");
                Assert.Throws<RemotingException>(() => obj.GetProcessId());

                // create object in restarted domain
                obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessId(), Is.Not.EqualTo(Process.GetCurrentProcess().Id));

            }

            var setupInfo = new ProcessDomainSetup
            {
                RestartOnProcessExit = false
            };

            // now restart should not occur
            using (var domain = ProcessDomain.CreateDomain("RemoteProcess2", setupInfo))
            {
                domain.Attached += () => attachedEvent.Set();
                domain.Detached += () => detachedEvent.Set();

                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);
                Assert.That(obj.GetProcessId(), Is.Not.EqualTo(Process.GetCurrentProcess().Id));

                attachedEvent.Reset();
                detachedEvent.Reset();

                Process.GetProcessById(obj.GetProcessId()).Kill();

                Assert.That(detachedEvent.WaitOne(10000), "Timed-out waiting for process to die");
                Assert.That(!attachedEvent.WaitOne(5000), "Unexpected re-attach");
                Assert.Throws<RemotingException>(() => obj.GetProcessId());
                Assert.Throws<RemotingException>(() => obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName));
            }
        }
        public void TestDeleteFileOnExit()
        {
            string desiredExecutableFileName = Path.Combine(Environment.CurrentDirectory, "ProcessDomain.exe");

            var setupInfo = new ProcessDomainSetup
            {
                ExecutableDirectory = Environment.CurrentDirectory,
                DeleteOnUnload = false
            };

            ProcessDomain.Unload(ProcessDomain.CreateDomain("ProcessDomain", setupInfo));
            Assert.That(File.Exists(desiredExecutableFileName));

            setupInfo.DeleteOnUnload = true;

            ProcessDomain.Unload(ProcessDomain.CreateDomain("ProcessDomain", setupInfo));
            Assert.That(!File.Exists(desiredExecutableFileName));
        }
        public void TestProcessPriority()
        {
            // Default case
            using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain"))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);
                Assert.That(obj.GetPriority(), Is.EqualTo(ProcessPriorityClass.Normal));
            }

            // Try each priority
            foreach (ProcessPriorityClass priority in Enum.GetValues(typeof(ProcessPriorityClass)))
            {
                var setup = new ProcessDomainSetup { PriorityClass = priority };
                using (var domain = ProcessDomain.CreateDomain("TestPriorityDomain", setup))
                {
                    var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(typeof(RemoteTestObject).Assembly.FullName, typeof(RemoteTestObject).FullName);
                    Assert.That(obj.GetPriority(), Is.EqualTo(priority));
                }
            }
        }
        public void TestTypeFilterLevel()
        {
            // using an event handler requires type filter level Full for a remoting channel

            // by default, it's low, which will fail
            using (var domain = ProcessDomain.CreateDomain("Domain"))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);

                Assert.Throws<SecurityException>(()=> obj.CallbackEvent += () => Assert.Fail("This should have failed"));
            }

            // now enable the remoting channel with type filter level Full
            var setup = new ProcessDomainSetup { TypeFilterLevel = TypeFilterLevel.Full };
            using (var domain = ProcessDomain.CreateDomain("Domain", setup))
            {
                var obj = (RemoteTestObject)domain.CreateInstanceAndUnwrap(TestObjectAssemblyName, TestObjectTypeName);

                obj.CalledBack = false;
                Assert.That(!obj.CalledBack);
                Assert.DoesNotThrow(() => obj.CallbackEvent += obj.SetCalledBack);
                obj.OnCallback();
                Assert.That(obj.CalledBack);
            }
        }
예제 #26
0
        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();
        }
예제 #27
0
 private static void SetupDllDirectories(ProcessDomainSetup setup)
 {
     if (!string.IsNullOrEmpty(setup.DllDirectory))
     {
         if (!WinApi.SetDllDirectory(setup.DllDirectory))
         {
             throw new Win32Exception();
         }
     }
 }