private static Task <ProcessResult> StartProcess(string command, int resultLimit, params string[] arguments)
        {
            var pars = new ProcessTaskParams {
                ResultLinesLimit = resultLimit
            };

            return(StartProcessFull(command, ProcessPriorityClass.Normal, pars, null, null, arguments));
        }
            private bool disposedValue; // To detect redundant calls

            public ProcessResult(Process proc, ProcessTaskParams parameters)
            {
                Parameters = parameters;
                Process    = proc;
            }
        private static Task <ProcessResult> StartProcessFull(
            string command,
            ProcessPriorityClass priorityClass,
            ProcessTaskParams parameters,
            Action <string> progress,
            CancellationToken?cancellation,
            params string[] arguments)
        {
            var proc = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName               = command,
                    Arguments              = string.Join(" ", arguments),
                    RedirectStandardError  = true,
                    RedirectStandardOutput = true,
                    CreateNoWindow         = true,
                    UseShellExecute        = false,
                    ErrorDialog            = false,
                    StandardOutputEncoding = Encoding.UTF8,
                    StandardErrorEncoding  = Encoding.UTF8,
                },
                EnableRaisingEvents = true,
            };

            var exited = new TaskCompletionSource <ProcessResult>();
            var result = new ProcessResult(proc, parameters);

            proc.Exited += (sender, args) =>
            {
                var exitcode = proc.ExitCode;
                if (exitcode == 0)
                {
                    exited.SetResult(result);
                }
                else
                {
                    exited.TrySetException(new InvalidOperationException(string.Join("\r\n", result.ErrorLines.Any() ? result.ErrorLines : result.ResultLines)));
                }

                proc.Dispose();
            };
            proc.ErrorDataReceived += (sender, args) =>
            {
                if (!string.IsNullOrWhiteSpace(args.Data))
                {
                    result.ErrorLines.AddLast(args.Data);
                    if ((result.Parameters.ErrorLinesLimit != -1) && (result.ErrorLines.Count > result.Parameters.ErrorLinesLimit))
                    {
                        result.ErrorLines.RemoveFirst();
                    }

                    progress?.Invoke(args.Data);
                }
            };
            proc.OutputDataReceived += (sender, args) =>
            {
                result.ResultLines.AddLast(args.Data);
                if ((result.Parameters.ResultLinesLimit != -1) && (result.ResultLines.Count > result.Parameters.ResultLinesLimit))
                {
                    result.ResultLines.RemoveFirst();
                }
            };

            proc.Start();
            proc.PriorityClass = priorityClass;
            proc.BeginErrorReadLine();
            proc.BeginOutputReadLine();

            cancellation?.Register(() =>
            {
                proc.Kill();
                proc.Dispose();
                exited.TrySetCanceled();
            });

            return(exited.Task);
        }