public static IRunner Fetch(string exe)
		{
			if (_domains == null)
				_domains = new Dictionary<string, WeakReference>(StringComparer.OrdinalIgnoreCase);

			exe = Path.GetFullPath(exe);
			WeakReference wref;
			AssemblyRunner worker;

			if (!_domains.TryGetValue(exe, out wref) || !wref.IsAlive || null == (worker = wref.Target as AssemblyRunner) || worker.IsDisposed)
				_domains[exe] = new WeakReference(worker = new AssemblyRunner(exe));

			GC.KeepAlive(worker);
			return worker;
		}
        public void TestUnloaded()
        {
            AppDomain domain = null;
            try
            {
                AssemblyRunner runner = new AssemblyRunner(Exe);
                //I hate using reflection for testing; however, sometimes it's best to be certain things are behaving as expected:
                domain = new PropertyValue<AppDomain>(runner, "_workerDomain").Value;
                runner = null;
            }
            catch { throw; }

            GC.Collect(0, GCCollectionMode.Forced);
            GC.WaitForPendingFinalizers();

            //The GC only starts the AppDomain unload within the ThreadPool, we have to wait for it to actually happen.
            DateTime max = DateTime.Now.AddMinutes(1);
            while(DateTime.Now < max)
                Assert.AreEqual(domain.Id, domain.Id);
        }
        public void TestStdOutputAndStdError()
        {
            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                StringWriter wtr = new StringWriter();
                StringWriter err = new StringWriter();
                ProcessOutputEventHandler handler =
                        delegate(object o, ProcessOutputEventArgs e)
                        { if (e.Error) err.WriteLine(e.Data); else wtr.WriteLine(e.Data); };

                runner.OutputReceived += handler;

                Assert.AreEqual(1, runner.Run("command-line-argrument"));
                Assert.AreEqual("std-err", err.ToString().Trim());

                StringReader rdr = new StringReader(wtr.ToString());
                Assert.AreEqual("WorkingDirectory = " + Environment.CurrentDirectory, rdr.ReadLine());
                Assert.AreEqual("argument[0] = command-line-argrument", rdr.ReadLine());
                Assert.AreEqual("std-input:", rdr.ReadLine());
                Assert.AreEqual(null, rdr.ReadLine());
            }
        }
 public void TestStandardInputFail()
 {
     using (IRunner runner = new AssemblyRunner(Exe))
     {
         runner.Start("-wait");
         runner.StandardInput.WriteLine();
     }
 }
 public void TestDisposal()
 {
     AssemblyRunner runner = new AssemblyRunner(Exe);
     runner.Dispose();
     Assert.IsTrue(runner.IsDisposed);
 }
 public void TestToString()
 {
     using (AssemblyRunner runner = new AssemblyRunner(Exe))
         Assert.AreEqual(Exe, runner.ToString());
 }
        public void TestKill()
        {
            Environment.CurrentDirectory = Path.GetDirectoryName(FileUtils.FindFullPath("cmd.exe"));

            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                ManualResetEvent gotExit = new ManualResetEvent(false);
                runner.ProcessExited += delegate(Object o, ProcessExitedEventArgs e) { gotExit.Set(); };
                Assert.IsFalse(runner.IsRunning);
                runner.Kill(); // always safe to call

                runner.Start("-wait");
                Assert.IsTrue(runner.IsRunning);

                try //make sure we can't start twice.
                {
                    runner.Start();
                    Assert.Fail();
                }
                catch (InvalidOperationException)
                { }

                Assert.IsFalse(runner.WaitForExit(TimeSpan.FromSeconds(1), false));
                runner.Kill();
                Assert.IsFalse(runner.IsRunning);
                Assert.IsTrue(gotExit.WaitOne(30000, false));
            }
        }
        public void TestExitedEventUnsubscribe()
        {
            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                int exitCode = -1;
                bool receivedExit = false;
                ProcessExitedEventHandler handler =
                        delegate(object o, ProcessExitedEventArgs e)
                        { receivedExit = true; exitCode = e.ExitCode; };

                runner.ProcessExited += handler;
                runner.ProcessExited -= handler;

                Assert.AreEqual(0, runner.Run());
                Assert.IsFalse(receivedExit);
                Assert.AreEqual(-1, exitCode);
            }
        }
        public void TestRunWithWorkingDirectory()
        {
            using (TempDirectory dir = new TempDirectory())
            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                List<string> lines = new List<string>();
                runner.OutputReceived += delegate(Object o, ProcessOutputEventArgs e) { lines.Add(e.Data); };

                Assert.AreNotEqual(dir.TempPath, runner.WorkingDirectory);
                runner.WorkingDirectory = dir.TempPath;
                Assert.AreEqual(dir.TempPath, runner.WorkingDirectory);

                int exitCode = runner.Run();
                Assert.AreEqual(0, exitCode);
                Assert.AreEqual("WorkingDirectory = " + dir.TempPath, lines[0]);
            }
        }
        public void TestRunWithInput()
        {
            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                List<string> lines = new List<string>();
                runner.OutputReceived += delegate(Object o, ProcessOutputEventArgs e) { lines.Add(e.Data); };
                int exitCode = runner.Run(new StringReader("Hello World\r\nWhatever!\r\nAnother line."));
                Assert.AreEqual(0, exitCode);

                // 0 == WorkingDirectory = 
                // 1 == std-input:
                Assert.AreEqual("Hello World", lines[2]);
                Assert.AreEqual("Whatever!", lines[3]);
                Assert.AreEqual("Another line.", lines[4]);
            }
        }
        public void TestOutputEventUnsubscribe()
        {
            using (AssemblyRunner runner = new AssemblyRunner(Exe))
            {
                bool outputReceived = false;
                ProcessOutputEventHandler handler =
                        delegate(object o, ProcessOutputEventArgs e)
                        { outputReceived = true; };

                runner.OutputReceived += handler;
                runner.OutputReceived -= handler;

                Assert.AreEqual(0, runner.Run());
                Assert.IsFalse(outputReceived);
            }
        }
 public void TestUnhandledExceptionRun()
 {
     using (IRunner runner = new AssemblyRunner(Exe))
     {
         runner.Run("-throw", "System.ArgumentOutOfRangeException");
         Assert.Fail();
     }
 }