public ToolExecutionResult(ToolExecutionOptions options, Process process)
		{
			this.Process = process;
			this.ProcessId = process.Id;
			this.ExitCode = int.MinValue;

			if (options.StartInfo.RedirectStandardOutput)
			{
				this.standartStreamOpenStatus |= StandartOutputOpened;
				this.standartOutputBuffer = new StringBuilder();
				process.OutputDataReceived += this.OnOutputDataReceived;
				process.BeginOutputReadLine();
			}
			if (options.StartInfo.RedirectStandardError)
			{
				this.standartErrorBuffer = new StringBuilder();
				this.standartStreamOpenStatus |= StandartErrorOpened;
				process.ErrorDataReceived += this.OnErrorDataReceived;
				process.BeginErrorReadLine();
			}
		}
        private static IEnumerable RunAsync(ToolExecutionOptions options)
        {
            yield return null;

            var isDotNetInstalled = false;

            if (IsWindows)
            {
                isDotNetInstalled = Get45or451FromRegistry() != null;
            }

            if (options.RequireDotNetRuntime && isDotNetInstalled == false)
            {
                if (string.IsNullOrEmpty(MonoPath))
                    throw new InvalidOperationException("No .NET runtime found on machine.");

                options.StartInfo.Arguments = ToolExecutionOptions.ConcatArguments(options.StartInfo.FileName) + " " + options.StartInfo.Arguments;
                options.StartInfo.FileName = MonoPath;
            }

            if (options.CaptureStandartError)
                options.StartInfo.RedirectStandardError = true;
            if (options.CaptureStandartOutput)
                options.StartInfo.RedirectStandardOutput = true;

            if (Settings.Current.Verbose)
                UnityEngine.Debug.Log(string.Format("Starting process '{0}' at '{1}' with arguments '{2}' and environment variables '{3}'.", options.StartInfo.FileName, options.StartInfo.WorkingDirectory, options.StartInfo.Arguments, ConcatDictionaryValues(options.StartInfo.EnvironmentVariables)));

            var processStarted = DateTime.UtcNow;
            var timeout = options.ExecutionTimeout;
            if (timeout <= TimeSpan.Zero)
                timeout = TimeSpan.MaxValue;

            var process = Process.Start(options.StartInfo);
            if (process == null)
                throw new InvalidOperationException("Unknown process start error.");

            var result = new ToolExecutionResult(options, process);
            if (options.WaitForExit == false)
            {
                //if (Settings.Current.Verbose)
                //	UnityEngine.Debug.Log(string.Format("Yielding started process '{0}' at '{1}' with arguments '{2}'.", options.StartInfo.FileName, options.StartInfo.WorkingDirectory, options.StartInfo.Arguments));
                yield return result;
                yield break;
            }

            var hasExited = false;
            while (hasExited == false)
            {
                if (DateTime.UtcNow - processStarted > timeout)
                    throw new TimeoutException();

                try
                {
                    process.Refresh();
                    hasExited = process.HasExited;
                }
                catch (InvalidOperationException)
                {
                    // ignored
                }
                catch (System.ComponentModel.Win32Exception)
                {
                    // ignored
                }
                yield return Promise.Delayed(TimeSpan.FromMilliseconds(50));
            }

            processStarted = DateTime.UtcNow;
            timeout = options.TerminationTimeout;
            if (timeout <= TimeSpan.Zero)
                timeout = TimeSpan.MaxValue;

            while (result.HasPendingData)
            {
                if (DateTime.UtcNow - processStarted > timeout)
                    throw new TimeoutException();

                yield return Promise.Delayed(TimeSpan.FromMilliseconds(50));
            }

            result.ExitCode = process.ExitCode;

            if (Settings.Current.Verbose)
                UnityEngine.Debug.Log(string.Format("Process #{1} '{0}' has exited with code {2}.", options.StartInfo.FileName, result.ProcessId, result.ExitCode));

            yield return result;
        }
        public static Promise<ToolExecutionResult> Run(ToolExecutionOptions options)
        {
            if (options == null) throw new ArgumentNullException("options");

            return new Coroutine<ToolExecutionResult>(RunAsync(options));
        }