private static TryGetOrUpdateFileFromFtp GetOrUpdateFileFromFtpLastModifiedDate(string fileName, DateTime?fileLastModifiedDateFromSql)
        {
            //Создаем папку для библиотек операций
            if (!Directory.Exists(MainSettings.Constants.PluginOperationDllDirectoryPath))
            {
                Directory.CreateDirectory(MainSettings.Constants.PluginOperationDllDirectoryPath);
            }

            if (!string.IsNullOrEmpty(fileName))
            {
                //Если файл существует, но его MD5 не совпадает с тем что в базе - удаляем его (он устаревший)
                if (File.Exists(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)) &&
                    !Extensions.IsNullableDateTimeIdentical(File.GetLastWriteTime(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)), fileLastModifiedDateFromSql))
                {
                    File.Delete(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName));
                }

                //Если файла не существует - закачиваем его
                if (!File.Exists(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)))
                {
                    FtpWorks.DownloadFileFromFtpOld(
                        Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName),
                        Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpServer, MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME, fileName),
                        MainSettings.GlobalSettings.SelfUpdateFtpUser,
                        MainSettings.GlobalSettings.SelfUpdateFtpPassword);
                }

                return(new TryGetOrUpdateFileFromFtp());
            }
            else
            {
                return(new TryGetOrUpdateFileFromFtp(false, "Ошибка вызова функции (GetOrUpdateFileFromFtp), неверные входные параметры"));
            }
        }
        private static TryGetOrUpdateFileFromFtp GetOrUpdateFileFromFtpMd5(string fileName, string fileMD5FromSql)
        {
            //Создаем папку для библиотек операций
            if (!Directory.Exists(MainSettings.Constants.PluginOperationDllDirectoryPath))
            {
                Directory.CreateDirectory(MainSettings.Constants.PluginOperationDllDirectoryPath);
            }

            if (!string.IsNullOrEmpty(fileName))
            {
                //Если файл существует, но его MD5 не совпадает с тем что в базе - удаляем его (он устаревший)
                if (File.Exists(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)) &&
                    !MD5Works.CompareHahes(MD5Works.GetFileHash(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)), fileMD5FromSql))
                {
                    File.Delete(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName));
                }

                //Если файла не существует - закачиваем его
                if (!File.Exists(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)))
                {
                    var res = FtpWorks.DownloadFileFromFtp(MainSettings.Constants.PluginOperationDllDirectoryPath
                                                           , MainSettings.GlobalSettings.SelfUpdateFtpServer
                                                           , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                                           , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                                           , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                                           , fileName);

                    if (!res.IsComplete)
                    {
                        return(new TryGetOrUpdateFileFromFtp(false, res.Message));
                    }
                }

                if (!File.Exists(Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName)))
                {
                    return(new Helpers.TryGetOrUpdateFileFromFtp(false, $"Ошибка закачки файла плагин-операции {fileName} по ftp"));
                }

                return(new TryGetOrUpdateFileFromFtp());
            }
            else
            {
                return(new TryGetOrUpdateFileFromFtp(false, "Ошибка вызова функции (GetOrUpdateFileFromFtp), неверные входные параметры"));
            }
        }
        public static List <string> GetUnregistredOrUnrelevantFileNamesLastmodifiedDate()
        {
            var res = new List <string>();

            var list = FtpWorks.GetFilesList(MainSettings.GlobalSettings.SelfUpdateFtpServer
                                             , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                             , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                             , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                             , ".dll");

            foreach (var fileName in list)
            {
                if (!IsFileRegisteregAndRelevantlastModifiedDate(fileName))
                {
                    res.Add(fileName);
                }
            }

            return(res);
        }
        private static bool IsFileRegisteregAndRelevantMd5(string fileName)
        {
            DataSet ds = SqlWorks.ExecProc("GetOperationTypeByFileName", fileName);

            if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
            {
                return(false);
            }
            else
            {
                string dllFullPath = Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath
                                                  , MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME
                                                  , fileName);

                var ftpFileMd5Result = FtpWorks.GetFtpFileMd5(MainSettings.GlobalSettings.SelfUpdateFtpServer
                                                              , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                                              , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                                              , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                                              , fileName);

                if (ftpFileMd5Result.IsComplete)
                {
                    try
                    {
                        DataRow dr = ds.Tables[0].Rows[0];
                        return(MD5Works.CompareHahes(ftpFileMd5Result.Value, Convert.ToString(dr["FileMD5"])));
                    }
                    catch
                    {
                        return(false);
                    }
                }
                else
                {
                    NLogger.LogErrorToBaseAndHdd(MainSettings.MainSqlSettings?.ComputerId, $"Ошибка получения MD5 файла ({dllFullPath})");
                    return(false);
                }
            }
        }
        private static bool IsFileRegisteregAndRelevantlastModifiedDate(string fileName)
        {
            DataSet ds = SqlWorks.ExecProc("GetOperationTypeByFileName", fileName);

            if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
            {
                return(false);
            }
            else
            {
                string dllFullPath = Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath
                                                  , MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME
                                                  , fileName);
                DateTime?ftpFileLastModifiedDate = FtpWorks.GetFileLastModifiedDate(MainSettings.GlobalSettings.SelfUpdateFtpServer
                                                                                    , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                                                                    , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                                                                    , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                                                                    , fileName);

                if (ftpFileLastModifiedDate.HasValue)
                {
                    try
                    {
                        DataRow dr = ds.Tables[0].Rows[0];
                        return(Extensions.IsNullableDateTimeIdentical(ftpFileLastModifiedDate, (DateTime?)dr["LastModifiedDate"]));
                    }
                    catch
                    {
                        return(false);
                    }
                }
                else
                {
                    NLogger.LogErrorToBaseAndHdd(MainSettings.MainSqlSettings?.ComputerId, $"Ошибка получения последней даты изменения файла ({dllFullPath})");
                    return(false);
                }
            }
        }
        public static TryRegisterPlugin RegisterOrUpdatePluginMd5(string nameRus, string fileName, int groupId = 1 /*стандартные операции*/, string description = "")
        {
            string dllLocalFullPath = Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName);

            string dllFtpFullPath = Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath
                                                 , MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME
                                                 , fileName);
            var ftpFileMd5Result = FtpWorks.GetFtpFileMd5(MainSettings.GlobalSettings.SelfUpdateFtpServer
                                                          , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                                          , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                                          , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                                          , fileName);

            if (ftpFileMd5Result.IsComplete)
            {
                try
                {
                    string  ftpFileMd5 = ftpFileMd5Result.Value;
                    DataSet ds         = SqlWorks.ExecProc("GetOperationTypeByFileName", fileName);
                    if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
                    {
                        //Регистрируем
                        //Актуализируем файл из фтп, если нужно
                        var res = GetOrUpdateFileFromFtpMd5(fileName, null);
                        if (!res.IsComplete)
                        {
                            return(new TryRegisterPlugin(false, $"Ошибка скачивания файла ({fileName}) с ftp в директорию ({MainSettings.Constants.PluginOperationDllDirectoryPath})"));
                        }
                        else
                        {
                            /*
                             * @Name nvarchar(512)
                             * ,@NameRus nvarchar(512)
                             * ,@GroupId int
                             * ,@FileName nvarchar(510)
                             * ,@FileMD5 nvarchar(64)
                             * ,@Description nvarchar(MAX)
                             */

                            //Пробуем получить имя типа операции
                            var dllResult = GetFromDll(dllLocalFullPath);
                            if (!dllResult.IsComplete)
                            {
                                return(new TryRegisterPlugin(false, $"Ошибка плучения типа операции из файла ({dllLocalFullPath})"));
                            }

                            SqlWorks.ExecProc("AddOperationType"
                                              , dllResult.PluginOperationInstance.SqlName
                                              , nameRus
                                              , groupId
                                              , fileName
                                              , null
                                              , ftpFileMd5
                                              , description);

                            return(new TryRegisterPlugin());
                        }
                    }
                    else
                    {
                        DataRow dr = ds.Tables[0].Rows[0];
                        //Обновляем, если нужно
                        if (!MD5Works.CompareHahes(ftpFileMd5, Convert.ToString(dr["FileMD5"])))
                        {
                            //Актуализируем файл из фтп, если нужно
                            var res = GetOrUpdateFileFromFtpMd5(fileName, Convert.ToString(dr["FileMD5"]));
                            if (!res.IsComplete)
                            {
                                return(new TryRegisterPlugin(false, $"Ошибка скачивания файла ({fileName}) с ftp в директорию ({MainSettings.Constants.PluginOperationDllDirectoryPath})"));
                            }
                            else
                            {
                                var dllResult = GetFromDll(dllLocalFullPath);
                                if (!dllResult.IsComplete)
                                {
                                    return(new TryRegisterPlugin(false, $"Ошибка плучения типа операции из файла ({dllLocalFullPath})"));
                                }

                                SqlWorks.ExecProc("UpdateOperationTypeById"
                                                  , Convert.ToInt32(dr["Id"])
                                                  , dllResult.PluginOperationInstance.SqlName
                                                  , nameRus
                                                  , groupId
                                                  , fileName
                                                  , null
                                                  , ftpFileMd5
                                                  , description);

                                return(new TryRegisterPlugin());
                            }
                        }

                        return(new TryRegisterPlugin());
                    }
                }
                catch (Exception ex)
                {
                    return(new TryRegisterPlugin(false, ex.ToString()));
                }
            }
            else
            {
                return(new TryRegisterPlugin(false, $"Не удалось получить MD5 файла ({fileName}) по ftp"));
            }
        }
        public static TryRegisterPlugin RegisterOrUpdatePluginLastModifiedDate(string fileName)
        {
            string dllLocalFullPath = Path.Combine(MainSettings.Constants.PluginOperationDllDirectoryPath, fileName);

            string dllFtpFullPath = Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath
                                                 , MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME
                                                 , fileName);
            DateTime?ftpFileLastModifiedDate = FtpWorks.GetFileLastModifiedDate(MainSettings.GlobalSettings.SelfUpdateFtpServer
                                                                                , MainSettings.GlobalSettings.SelfUpdateFtpUser
                                                                                , MainSettings.GlobalSettings.SelfUpdateFtpPassword
                                                                                , Path.Combine(MainSettings.GlobalSettings.SelfUpdateFtpPath, MainSettings.Constants.OPERATION_PLUGIN_DIRECTORY_NAME)
                                                                                , fileName);

            if (ftpFileLastModifiedDate.HasValue)
            {
                try
                {
                    DataSet ds = SqlWorks.ExecProc("GetOperationTypeByFileName", fileName);
                    if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
                    {
                        //Регистрируем
                        //Актуализируем файл из фтп, если нужно
                        var res = GetOrUpdateFileFromFtpLastModifiedDate(fileName, null);
                        if (!res.IsComplete)
                        {
                            return(new TryRegisterPlugin(false, $"Ошибка скачивания файла ({fileName}) с ftp в директорию ({MainSettings.Constants.PluginOperationDllDirectoryPath})"));
                        }
                        else
                        {
                            /*
                             * @Name nvarchar(512)
                             * ,@NameRus nvarchar(512)
                             * ,@GroupId int
                             * ,@FileName nvarchar(510)
                             * ,@FileMD5 nvarchar(64)
                             * ,@Description nvarchar(MAX)
                             */

                            //Пробуем получить имя типа операции
                            var dllResult = GetFromDll(dllLocalFullPath);
                            if (!dllResult.IsComplete)
                            {
                                return(new TryRegisterPlugin(false, $"Ошибка получения типа операции из файла ({dllLocalFullPath})"));
                            }

                            var addDs = SqlWorks.ExecProc("AddOperationType"
                                                          , dllResult.PluginOperationInstance.SqlName
                                                          , ""
                                                          , 1
                                                          , fileName
                                                          , ftpFileLastModifiedDate
                                                          , MD5Works.GetFileHash(dllLocalFullPath).ToUpper()
                                                          , "");

                            if (addDs != null && addDs.Tables.Count > 0 && addDs.Tables[0].Rows.Count > 0)
                            {
                                int id = ConvertSafe.ToInt32(addDs.Tables[0].Rows[0]["Id"]);
                                foreach (var param in dllResult.PluginOperationInstance.RegistrationParams)
                                {
                                    var resDs = SqlWorks.ExecProc("UpdateOperationTypesFieldsById"
                                                                  , id
                                                                  , param.Key
                                                                  , param.Value);

                                    if (resDs != null && resDs.Tables.Count > 0 && resDs.Tables[0].Rows.Count > 0)
                                    {
                                        if (Convert.ToInt32(resDs.Tables[0].Rows[0]["ResultId"]) == -1)
                                        {
                                            return(new TryRegisterPlugin(false, $"Ошибка записи параметров SQL из файла ({dllLocalFullPath}). SQL Error: {Convert.ToString(resDs.Tables[0].Rows[0]["Message"])}"));
                                        }
                                    }
                                    else
                                    {
                                        return(new TryRegisterPlugin(false, $"Ошибка записи параметров SQL из файла ({dllLocalFullPath})"));
                                    }
                                }
                            }

                            return(new TryRegisterPlugin());
                        }
                    }
                    else
                    {
                        DataRow  dr          = ds.Tables[0].Rows[0];
                        DateTime?sqlDateTime = null;
                        try
                        {
                            sqlDateTime = (DateTime?)dr["LastModifiedDate"];
                        }
                        catch
                        {
                            sqlDateTime = null;
                        }
                        //Обновляем, если нужно
                        if (!Extensions.IsNullableDateTimeIdentical(ftpFileLastModifiedDate, sqlDateTime))
                        {
                            //Актуализируем файл из фтп, если нужно
                            var res = GetOrUpdateFileFromFtpLastModifiedDate(fileName, sqlDateTime);
                            if (!res.IsComplete)
                            {
                                return(new TryRegisterPlugin(false, $"Ошибка скачивания файла ({fileName}) с ftp в директорию ({MainSettings.Constants.PluginOperationDllDirectoryPath})"));
                            }
                            else
                            {
                                var dllResult = GetFromDll(dllLocalFullPath);
                                if (!dllResult.IsComplete)
                                {
                                    return(new TryRegisterPlugin(false, $"Ошибка получения типа операции из файла ({dllLocalFullPath})"));
                                }

                                SqlWorks.ExecProc("UpdateOperationTypeById"
                                                  , Convert.ToInt32(dr["Id"])
                                                  , dllResult.PluginOperationInstance.SqlName
                                                  , ""
                                                  , 1
                                                  , fileName
                                                  , ftpFileLastModifiedDate
                                                  , MD5Works.GetFileHash(dllLocalFullPath).ToUpper()
                                                  , "");

                                foreach (var param in dllResult.PluginOperationInstance.RegistrationParams)
                                {
                                    var resDs = SqlWorks.ExecProc("UpdateOperationTypesFieldsById"
                                                                  , Convert.ToInt32(dr["Id"])
                                                                  , param.Key
                                                                  , param.Value);

                                    if (resDs != null && resDs.Tables.Count > 0 && resDs.Tables[0].Rows.Count > 0)
                                    {
                                        if (Convert.ToInt32(resDs.Tables[0].Rows[0]["ResultId"]) == -1)
                                        {
                                            return(new TryRegisterPlugin(false, $"Ошибка записи параметров SQL из файла ({dllLocalFullPath}). SQL Error: {Convert.ToString(resDs.Tables[0].Rows[0]["Message"])}"));
                                        }
                                    }
                                    else
                                    {
                                        return(new TryRegisterPlugin(false, $"Ошибка записи параметров SQL из файла ({dllLocalFullPath})"));
                                    }
                                }

                                return(new TryRegisterPlugin());
                            }
                        }

                        return(new TryRegisterPlugin());
                    }
                }
                catch (Exception ex)
                {
                    return(new TryRegisterPlugin(false, ex.ToString()));
                }
            }
            else
            {
                return(new TryRegisterPlugin(false, $"Не удалось получить дату последнего изменения файла ({fileName}) по ftp"));
            }
        }