private ETLUpdateRecord AddUpdateRecord(string file)
        {
            string extension = Path.GetExtension(file).Replace(".", string.Empty);
            string fileName  = Path.GetFileName(file);
            // На программу подразумевается одна конфигурация и один модуль
            ETLProcess prc = pumps.FirstOrDefault(p => extension.IsMatch("json")
                ? p.Config == fileName
                : p.Module == fileName);

            // В реестре закачка отсутствует, есть только программный модуль
            if (prc == null && extension.IsMatch("dll"))
            {
                return(null);
            }

            ETLUpdateRecord rec = null;

            switch (extension)
            {
            case "json":
                JObject data      = JsonCommon.Load(file);
                string  programID = prc == null ? data["id"].ToString() : prc.ProgramID;

                rec = new ETLUpdateRecord {
                    Config    = fileName,
                    Module    = data["module"].ToString(),
                    ProgramID = programID
                };

                Updates[programID] = rec;
                break;

            case "dll":
                // Если записи нет, то добавляем, иначе нужный модуль уже должен быть прописан в обновление
                if (!Updates.ContainsKey(prc.ProgramID))
                {
                    rec = new ETLUpdateRecord {
                        ProgramID = prc.ProgramID,
                        Module    = fileName
                    };

                    Updates.Add(prc.ProgramID, rec);
                }
                break;
            }

            return(rec);
        }
        private void WatcherHandler(object sender, FileSystemEventArgs e)
        {
            if (!Path.GetExtension(e.Name).IsMatch("json|dll"))
            {
                return;
            }

            ETLUpdateRecord rec = AddUpdateRecord(e.FullPath);

            if (rec == null)
            {
                return;
            }

            // Событие получения обновления
            OnReceiveUpdate?.Invoke(this, new ReceiveUpdateEventArgs {
                UpdateInfo = rec
            });
        }
        /// <summary>
        /// Применение обновлений
        /// </summary>
        public void ApplyUpdate(ETLUpdateRecord rec, ETLHistory history)
        {
            ETLProcess prc = pumps.FirstOrDefault(p => p.ProgramID == rec.ProgramID);

            // Копирование файлов в необходимые директории
            if (!string.IsNullOrEmpty(rec.Config))
            {
                MoveFile(rec.Config, settings.UpdatesPath, settings.ProgramsPath);

                // Обноление конфигурации загруженных в реестр закачек или добавление новой
                string configFile = Path.Combine(settings.ProgramsPath, rec.Config);
                if (prc == null)
                {
                    pumps.Add(new ETLProcess(configFile, history));
                }
                else
                {
                    prc.Init(configFile);
                }
            }

            if (!string.IsNullOrEmpty(rec.Module))
            {
                // Модуль
                MoveFile(rec.Module, settings.UpdatesPath, settings.ModulesPath);

                // Отладочные данные
                MoveFile(rec.Module.Replace("dll", "pdb"), settings.UpdatesPath, settings.ModulesPath);
            }

            // Удаление применённого обновления из списка доступных
            Updates.Remove(rec.ProgramID);

            // Событие обновления
            OnUpdate?.Invoke(this, new UpdateEventArgs {
                UpdateInfo = rec
            });
        }