protected virtual bool CheckCodeBlock(RunOptsBase opts, ref RunResult runResult)
		{
			if (opts.CodeBlock == null)
				opts.CodeBlock = new ConsoleOrScriptCodeBlock { CodeBlock = string.Empty };
			else if (((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock == null)
				((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock = string.Empty;

			return CheckCodeSizeLimit(((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock, ref runResult);
		}
		protected override bool CheckCodeBlock(RunOptsBase opts, ref RunResult runResult)
		{
			if (opts.CodeBlock == null)
				opts.CodeBlock = new MvcCodeBlock
					{
						Model = string.Empty,
						View = string.Empty,
						Controller = string.Empty
					};

			var codeBlock = (MvcCodeBlock) opts.CodeBlock;

			return CheckCodeSizeLimit(codeBlock.Model, ref runResult) &&
					CheckCodeSizeLimit(codeBlock.Controller, ref runResult);
		}
		protected override void RunInteractive(RunOptsBase opts, RunResult result)
		{
			new PermissionSet(PermissionState.Unrestricted).Assert();

			CommonScriptEngine scriptEngine = this.CreateSciptEngine();
			Session session = scriptEngine.CreateSession();
			var codeBlock = (ConsoleOrScriptCodeBlock) opts.CodeBlock;
			var referencedDlls = this.GetGacDlls(codeBlock.CodeBlock);
			foreach (var referenceDll in referencedDlls)
				session.AddReference(referenceDll);

			var libs = GetNonGacDlls();

			foreach (var path in libs)
			{
				session.AddReference(path);
			}

			Submission<object> submission;
			try
			{
				// we compile code there
				submission = session.CompileSubmission<object>(codeBlock.CodeBlock);
			}
			catch (ThreadAbortException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if (!string.IsNullOrEmpty(ex.Message) && ex.Message.Contains(ErrorWhenCompileConsoleProjectAsScript))
				{/*Case 4067: DotNetFiddle throws exception on VbNet Script
				  * https://entech.fogbugz.com/default.asp?4067#31607
				  * This issue occurs, when user is trying to compile VB.Net Console project as VB.Net Script project.
				  * So, there is main entry point 'Module Sub Main' in snippet.
				  * Then Roslyn throws following exception "(3) : error BC35000: Requested operation is not available because the runtime library function 'Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute..ctor' is not defined."
				  * In same case for C#, Roslyn just ignores 'console' code.
				  * So for VB.Net case we just return 'success' and empty string.
				  */
					result.IsSuccess = true;
					result.ConsoleOutput = "";
				}
				else
				{
					ValidateCodeResult validateCodeResult = ValidateCode(codeBlock.CodeBlock);

					result.IsSuccess = false;
					result.FailureType = RunResultFailureType.CompilerErrors;
					result.CompilerErrors = validateCodeResult.Errors;
				}

				if (result.CompilerErrors == null)
				{
					result.CompilerErrors = new List<ValidationError> {ValidationError.CreateFromException(ex)};
				}

				TryCleanRoslynCacheHack();
				PermissionSet.RevertAssert();
				return;
			}


			object execResult = null;
			try
			{
				this.OnStartingExecution();
				
				PermissionSet.RevertAssert();

				execResult = submission.Execute();

				this.OnFinishedExecution();
			}
			catch (ThreadAbortException)
			{
				throw;
			}
			catch (Exception ex)
			{
				result.IsSuccess = false;
				result.FailureType = RunResultFailureType.RunTimeException;
				result.RunTimeException = new ExceptionInfo(ex);
			}
			finally
			{
				result.ConsoleOutput = _consoleWriter.ToString().TrimEnd();

				if (execResult != null)
				{
					result.ConsoleOutput += Environment.NewLine;
					result.ConsoleOutput += "[Return value]: " + execResult;
				}

				// don't need it as we modified Roslyn assemblies and made fix in them
				// TryCleanRoslynCacheHack();
			}
		}
		protected virtual void RunMvc(RunOptsBase opts, RunResult result)
		{
			throw new NotImplementedException();
		}
		protected abstract void RunInteractive(RunOptsBase opts, RunResult result);
		private void RunConsole(RunOptsBase opts, RunResult result)
		{
			new PermissionSet(PermissionState.Unrestricted).Assert();

			CompilerResults compilerResults;
			compilerResults = CompileConsole(opts, 4);

			if (!IsCompilationSucceed(compilerResults, result))
			{
				PermissionSet.RevertAssert();
				return;
			}


			MethodInfo mainMethodInfo;
			object ownerInstance;

			mainMethodInfo = GetMainMethodAndOwnerInstance(compilerResults.CompiledAssembly, out ownerInstance);

			if (mainMethodInfo == null || !mainMethodInfo.IsPublic || !mainMethodInfo.DeclaringType.IsPublic)
			{
				result.IsSuccess = false;
				result.FailureType = RunResultFailureType.FatalError;
				result.FatalErrorMessage = "Public Main() method is required in a public class";
				return;
			}


			try
			{
				this.OnStartingExecution();
				PermissionSet.RevertAssert();

				//Add timer so doesn't execute for more then 5 secs
				var paramInfos = mainMethodInfo.GetParameters();
				mainMethodInfo.Invoke(ownerInstance, paramInfos.Select(pi => (object)null).ToArray());

				this.OnFinishedExecution();
			}
			catch (ThreadAbortException)
			{
				throw;
			}
			catch (Exception ex)
			{
				result.IsSuccess = false;
				result.FailureType = RunResultFailureType.RunTimeException;
				result.RunTimeException = new ExceptionInfo(ex.InnerException ?? ex);
			}
			finally
			{
				result.ConsoleOutput = _consoleWriter.ToString().TrimEnd();
			}
		}
		protected bool IsCompilationSucceed(CompilerResults compilerResults, RunResult result)
		{
			if (compilerResults.Errors.HasErrors)
			{
				result.IsSuccess = false;
				result.FailureType = RunResultFailureType.CompilerErrors;
				result.CompilerErrors = GetValidationErrorsFromCompilerErrors(compilerResults.Errors);
				return false;
			}
			return true;
		}
		public RunResult Run(RunOptsBase opts)
		{
			RunResult result = null;
			if (!CheckCodeBlock(opts, ref result))
				return result;

			// we should copy it before running, becuase it can be changed during execution
			var sandboxFolder = _sandboxFolder;

			var codeHelper = SandboxHelper.ExecuteInFullTrust(() =>(CodeHelper)Activator.CreateInstance(_codeHelperType));
			codeHelper.NuGetDllReferences = opts.NuGetDllReferences;

			codeHelper.StartingExecution += this.CodeHelper_StartingExecution;
			codeHelper.FinishedExecution += this.CodeHelper_FinishedExecution;
			codeHelper.RequestedConsoleInput += this.CodeHelper_RequestedConsoleInput;

			_executingThread = new Thread(
				() =>
				{
					try
					{
						_runAt = DateTime.Now;
						result = this.ExecuteCodeBlock(opts, codeHelper);
					}
					finally
					{
						// in theory in can be null at this point if something bad happened....
						if (result == null)
						{
							result = new RunResult() { FailureType = RunResultFailureType.FatalError, IsSuccess = false };
						}

						result.Stats = SandboxHelper.ExecuteInFullTrust(() => GatherStatistics());
						_compilationCompleted.Set();
					}
				});

			_executingThread.Start();

			var monitoringTask = Task.Factory.StartNew(MonitorHealth, _tokenSource.Token);

			// wait for compilation. Just to be sure we have 15 seconds timeout
			_compilationCompleted.WaitOne(TimeSpan.FromSeconds(15));

			// if something happened during compilation, then we fire _compilationCompleted on exit, and result will be filled, so we just need to return it
			if (result != null)
			{
				return result;
			}

			// it will use some time for compilation
			// it can hungs for some unmanaged call like Console.ReadKey(), so we wait with timeout
			// we might need to rewrite it to ManualEvent that will be fired when CodeHelper starts execution
			_executingThread.Join(WorkerConfiguration.Current.ExecutionLimitTimeoutMs * 2);

			_tokenSource.Cancel();

			// we can't move it to new method, as it can be executed via reflection
			SandboxHelper.ExecuteInFullTrust(
				() =>
				{
					try
					{
						if (Directory.Exists(sandboxFolder))
						{
							foreach (var file in Directory.EnumerateFiles(sandboxFolder, "*", SearchOption.AllDirectories))
							{
								File.Delete(file);
							}
						}
					}
					catch
					{
						if (result != null)
							result.SandboxUnloadReason = SandboxUnloadReason.ClearDirFailed;
					}
				});

			return result;
		}
 protected abstract void RunInteractive(RunOptsBase opts, RunResult result);
		public RunResult Run(RunOptsBase opts)
		{
			var result = new RunResult();
			result.IsSuccess = true;

			_consoleReader.InputLines = opts.ConsoleInputLines;

			if (!VerifyDeniedCodeBlock(opts, result))
			{
				return result;
			}

			ResolveEventHandler handler = (o, e) => CurrentDomain_AssemblyResolve(opts, e);

			TextWriter defaultConsoleOut = Console.Out;
			TextReader defaultConsoleIn = Console.In;

			SandboxHelper.ExecuteInFullTrust(
				() =>
				{
					Console.SetOut(_consoleWriter);
					Console.SetIn(_consoleReader);
				});

			try
			{
				AppDomain.CurrentDomain.AssemblyResolve += handler;

				switch (ProjectType)
				{
					case ProjectType.Console:
						RunConsole(opts, result);
						break;
					case ProjectType.Script:
						RunInteractive(opts, result);
						break;
					case ProjectType.Mvc:
						RunMvc(opts, result);
						break;
					default:
						throw new NotImplementedException();
				}
			}
			catch (ThreadAbortException ex)
			{
				var consoleInputRequest = ex.ExceptionState as ConsoleInputRequest;
				if (consoleInputRequest != null)
				{
					result.IsSuccess = true;
					result.IsConsoleInputRequested = true;
				}
				else
				{
					result.IsSuccess = false;

					var limit = ex.ExceptionState as LimitExceededException;
					if (limit != null)
					{
						result.FailureType = RunResultFailureType.FatalError;
						result.FatalErrorMessage = LimitExceededException.FormatMessage(limit.LimitType);
					}
				}

				SandboxHelper.ExecuteInFullTrust(Thread.ResetAbort);
			}
			finally
			{
				//Restore Console Out just in case
				SandboxHelper.ExecuteInFullTrust(
					() =>
					{
						Console.SetOut(defaultConsoleOut);
						Console.SetIn(defaultConsoleIn);
					});

				// unsubscribe
				AppDomain.CurrentDomain.AssemblyResolve -= handler;
			}

			return result;
		}
 protected override bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result)
 {
     var codeBlock = ((NancyFxCodeBlock) opts.CodeBlock);
     var aggregateCode = codeBlock.Controller + codeBlock.Module;
     return VerifyDeniedCode(aggregateCode, result);
 }
        protected virtual void RunNancyFx(RunOptsBase opts, RunResult result)
        {
            CompilerResults compilerResults;
            compilerResults = CompileNancyFx(opts, 4);

            RunConsole(compilerResults, result);
        }
	    private void RunConsole(RunOptsBase opts, RunResult result)
	    {
            CompilerResults compilerResults;
            compilerResults = CompileConsole(opts, 4);

	        RunConsole(compilerResults, result);
	    }
		protected bool CheckCodeSizeLimit(string code, ref RunResult runResult)
		{
			if (code.Length > WorkerConfiguration.Current.ExecutionCodeMaxSize)
			{
				runResult = new RunResult
				{
					IsSuccess = false,
					FailureType = RunResultFailureType.FatalError,
					FatalErrorMessage = LimitExceededException.FormatMessage(LimitType.CodeSize)
				};
				return false;
			}

			return true;
		}
        public RunResult Run(RunOptsBase opts)
        {
            var result = new RunResult();

            result.IsSuccess = true;

            _consoleReader.InputLines = opts.ConsoleInputLines;

            if (!VerifyDeniedCodeBlock(opts, result))
            {
                return(result);
            }

            ResolveEventHandler handler = (o, e) => CurrentDomain_AssemblyResolve(opts, e);

            TextWriter defaultConsoleOut = Console.Out;
            TextReader defaultConsoleIn  = Console.In;

            SandboxHelper.ExecuteInFullTrust(
                () =>
            {
                Console.SetOut(_consoleWriter);
                Console.SetIn(_consoleReader);
            });

            try
            {
                AppDomain.CurrentDomain.AssemblyResolve += handler;

                switch (ProjectType)
                {
                case ProjectType.Console:
                    RunConsole(opts, result);
                    break;

                case ProjectType.Script:
                    RunInteractive(opts, result);
                    break;

                case ProjectType.Mvc:
                    RunMvc(opts, result);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
            catch (ThreadAbortException ex)
            {
                var consoleInputRequest = ex.ExceptionState as ConsoleInputRequest;
                if (consoleInputRequest != null)
                {
                    result.IsSuccess = true;
                    result.IsConsoleInputRequested = true;
                }
                else
                {
                    result.IsSuccess = false;

                    var limit = ex.ExceptionState as LimitExceededException;
                    if (limit != null)
                    {
                        result.FailureType       = RunResultFailureType.FatalError;
                        result.FatalErrorMessage = LimitExceededException.FormatMessage(limit.LimitType);
                    }
                }

                SandboxHelper.ExecuteInFullTrust(Thread.ResetAbort);
            }
            finally
            {
                //Restore Console Out just in case
                SandboxHelper.ExecuteInFullTrust(
                    () =>
                {
                    Console.SetOut(defaultConsoleOut);
                    Console.SetIn(defaultConsoleIn);
                });

                // unsubscribe
                AppDomain.CurrentDomain.AssemblyResolve -= handler;
            }

            return(result);
        }
 protected virtual bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result)
 {
     return(VerifyDeniedCode(((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock, result));
 }
		protected bool VerifyDeniedCode(string code, RunResult result)
		{
			Verify.Argument.IsNotNull(code, "code");
			const string DeniedCode = "PermissionSet";

			if (code.IndexOf(DeniedCode, StringComparison.CurrentCultureIgnoreCase) == -1)
			{
				return true;
			}

			result.IsSuccess = false;
			result.FatalErrorMessage = "Using PermissionSet is not allowed due to security reasons";
			result.FailureType = RunResultFailureType.FatalError;

			return false;
		}
 protected virtual void RunMvc(RunOptsBase opts, RunResult result)
 {
     throw new NotImplementedException();
 }
		protected virtual bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result)
		{
			return VerifyDeniedCode(((ConsoleOrScriptCodeBlock) opts.CodeBlock).CodeBlock, result);
		}