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)); } } }
/// <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); }
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); }
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); }
/// <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 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 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(); } } }
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 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)); }
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 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); } }