private string LaunchAvrDude(AvrDudeMemoryType MemoryType, AvrDudeMemoryOperationType Operation, string Input, AvrDudeInputFormat InputFormat,
                                     IProgressToken ProgressToken, CancellationToken CancellationToken)
        {
            Process p = _toolLauncher.Execute(_toolBody,
                                              new ConnectionAvrDudeParameter(AvrIspConnectionType.Usb),
                                              new ProgrammerIdAvrDudeParameter(_programmerKind),
                                              new IgnoreSignatureAvrDudeParameter(),
                                              new ChipIdAvrDudeParameter(_chipPseudoname),
                                              new UCommandParameter(MemoryType,
                                                                    Operation,
                                                                    Input,
                                                                    InputFormat));
            using (CancellationToken.Register(p.Kill))
            {
                var subtokens = new[]
                                {
                                    new SubprocessProgressToken(0.1),
                                    new SubprocessProgressToken(1.0),
                                    new SubprocessProgressToken(2.0)
                                };

                string output = string.Empty;
                using (new CompositeProgressManager(ProgressToken, subtokens))
                {
                    IEnumerator tokensEnumerator = subtokens.GetEnumerator();
                    IProgressController progressController = null;
                    bool calculatingProgress = false;
                    int counter = 0;

                    while (true)
                    {
                        CancellationToken.ThrowIfCancellationRequested();
                        int x = p.StandardError.Read();
                        if (x != -1)
                        {
                            var c = (char)x;
                            output += c;
                            Debug.Write(c);

                            if (c == '|')
                            {
                                if (!calculatingProgress)
                                {
                                    bool tokenExists = tokensEnumerator.MoveNext();
                                    calculatingProgress = true;
                                    counter = 0;
                                    progressController =
                                        _progressControllerFactory.CreateController(tokenExists ? (IProgressToken)tokensEnumerator.Current : null);
                                    progressController.SetProgress(0);
                                }
                                else
                                {
                                    calculatingProgress = false;
                                    progressController.Dispose();
                                }
                            }
                            if (c == '#' && calculatingProgress)
                            {
                                counter++;
                                progressController.SetProgress(counter / 50.0);
                            }
                        }
                        else if (p.HasExited)
                            break;
                    }
                }

                CancellationToken.ThrowIfCancellationRequested();

                if (output.Contains("did not find any USB device \"usb\"") ||
                    output.Contains("device not found"))
                    throw new ProgrammerNotConnectedAvrDudeException(output);

                if (output.Contains("Invalid device signature"))
                    throw new InvalidDeviceSignatureAvrDudeException(output);

                if (output.Contains("initialization failed"))
                    throw new DeviceNotConnectedAvrDudeException(output);

                if (output.Contains("verification error"))
                    throw new VerificationErrorAvrDudeException(output);

                if (!output.Contains("written") || !output.Contains("verified"))
                    throw new AvrDudeException("Неизвестная ошибка при работе с AVRDude", output);

                return string.Empty;
            }
        }
 /// <summary>Создаёт параметр команды на выполнение операции</summary>
 /// <param name="MemoryType">Тип оперируемой памяти</param>
 /// <param name="Operation">Тип операции</param>
 /// <param name="Input">Входные данные</param>
 /// <param name="InputFormat">Формат входных данных</param>
 public UCommandParameter(AvrDudeMemoryType MemoryType, AvrDudeMemoryOperationType Operation, string Input,
                          AvrDudeInputFormat InputFormat = AvrDudeInputFormat.Auto)
 {
     this.Input = Input;
     this.MemoryType = MemoryType;
     this.Operation = Operation;
     this.InputFormat = InputFormat;
 }