private string SetupProcess(IRequestContext client, RpcProcess process,
                                    IProcessTask <string, List <string> > task = null, RaiseUntilDetachOutputProcess outputProcessor = null)
        {
            var         id   = process.Id;
            ContextData data = default;

            var processExists = processes.TryGetValue(process.Id, out data);

            if (task == null && (!processExists || data.Task.IsCompleted))
            {
                outputProcessor = new RaiseUntilDetachOutputProcess();
                task            = new ProcessTaskWithListOutput <string>(taskManager, processEnvironment,
                                                                         outputProcessor: outputProcessor, token: cts.Token);
                processManager.Configure(task, process.StartInfo.ToStartInfo());
            }
            else if (task != null)
            {
                task.Dispose();
                task = null;
            }

            data = processes.GetOrAdd(id, data);

            data.Process = process;
            data.Client  = client;
            if (task != null)
            {
                data.Task            = task;
                data.OutputProcessor = outputProcessor;
            }

            if (data.Notifications == null)
            {
                data.Notifications =
                    new SynchronizationContextTaskScheduler(new ThreadSynchronizationContext(cts.Token));
            }

            processes[id] = data;

            HookupProcessHandlers(data);

            return(id);
        }
        public string Prepare(IRequestContext client, string executable, string arguments, ProcessOptions options,
                              string workingDir, string accessToken)
        {
            if (accessToken != this.accessToken)
            {
                throw new UnauthorizedAccessException();
            }
            if (cts.IsCancellationRequested)
            {
                return(null);
            }

            var outputProcessor = new RaiseUntilDetachOutputProcess();
            var task            = new NativeProcessListTask <string>(taskManager, processEnvironment, executable, arguments,
                                                                     outputProcessor: outputProcessor, cts.Token)
                                  .Configure(processManager, workingDir);

            var startInfo = ProcessInfo.FromStartInfo(task.Wrapper.StartInfo);
            var id        = options.MonitorOptions == MonitorOptions.KeepAlive ? startInfo.GetId() : Guid.NewGuid().ToString();

            SetupProcess(client, new RpcProcess(id, startInfo, options), task, outputProcessor);

            return(id);
        }