diff --git a/README.md b/README.md
index bcc753c..73e0c3e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,12 @@
# Что такое ANB Software Components Pack?
-ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка.
-Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС.
+ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка. Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС.
+
+# Лицензия
+MIIT
+
+# anbsoftware_componentspack
+some classes that extend the capabilities of the C # language
# Лицензия
-MIIT
+MIIT
\ No newline at end of file
diff --git a/anbs_cp/Classes/ActionError.cs b/anbs_cp/Classes/ActionError.cs
new file mode 100644
index 0000000..fd6906e
--- /dev/null
+++ b/anbs_cp/Classes/ActionError.cs
@@ -0,0 +1,63 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс ошибки
+///
+public sealed class ActionError: IActionError
+{
+ ///
+ /// Критичность ошибки:
+ /// при некритичных ошибках продолжение выполнения операции возможно,
+ /// а при критичных -- нет
+ ///
+ public bool IsCritical { get; init; }
+
+ ///
+ /// Объект ошибки
+ ///
+ public object Object { get; set; }
+
+ ///
+ /// Сообщение об ошибке
+ ///
+ public string Message { get; set; }
+
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public ActionError ()
+ {
+ IsCritical = true;
+ Object = "Not Implemented";
+ Message = "Not Implemented";
+ }
+
+ ///
+ /// Конструктор с 2 параметрами
+ ///
+ /// Сообщение
+ /// Критичность ошибки
+ public ActionError (string message, bool isCritical = true)
+ {
+ IsCritical = isCritical;
+ Object = "";
+ Message = message;
+ }
+
+ ///
+ /// Конструктор с 3 параметрами
+ ///
+ /// Объект ошибки
+ /// Сообщение
+ /// Критичность ошибки
+ public ActionError (object eObject, string message, bool isCritical = true)
+ {
+ IsCritical = isCritical;
+ Object = eObject;
+ Message = message;
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/ActionInfo.cs b/anbs_cp/Classes/ActionInfo.cs
new file mode 100644
index 0000000..e2acadf
--- /dev/null
+++ b/anbs_cp/Classes/ActionInfo.cs
@@ -0,0 +1,49 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс предупреждения
+///
+public sealed class ActionInfo: IActionInfo
+{
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public ActionInfo ()
+ {
+ IsStatusInfo = false;
+ Object = string.Empty;
+ Message = string.Empty;
+ }
+
+ ///
+ /// Конструктор
+ ///
+ /// Объект
+ /// Сообщение
+ /// Является статусной информацией?
+ public ActionInfo (string eObject, string message, bool isStatus = false)
+ {
+ IsStatusInfo = isStatus;
+ Object = eObject;
+ Message = message;
+ }
+ #endregion
+
+ #region Реализация интерфейса
+ ///
+ /// Объект
+ ///
+ public object Object { get; set; }
+ ///
+ /// Сообщение
+ ///
+ public string Message { get; set; }
+ ///
+ /// Статусная информация (например, начало работы)
+ ///
+ public bool IsStatusInfo { get; init; }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/ActionState.cs b/anbs_cp/Classes/ActionState.cs
new file mode 100644
index 0000000..1bba81d
--- /dev/null
+++ b/anbs_cp/Classes/ActionState.cs
@@ -0,0 +1,337 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Состояние действия
+///
+/// Обновлено 2023.11.1
+/// * Добавлен возвращаемый результат
+///
+/// Обновлено 2023.01.121.1:
+/// * Заменены интерфейсы IAction* на соответствующие классы
+///
+public class ActionState
+{
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public ActionState ()
+ {
+ Info = new();
+ Warnings = new();
+ Errors = new();
+ Value = default;
+ }
+
+ ///
+ /// Конструктор с указанием начального значения
+ ///
+ /// Начальное значение
+ public ActionState (T defaultValue)
+ {
+ Info = new();
+ Warnings = new();
+ Errors = new();
+ Value = defaultValue;
+ }
+
+ ///
+ /// Список информации
+ ///
+ public List Info { get; }
+
+ ///
+ /// Список предупреждений
+ ///
+ public List Warnings { get; }
+
+ ///
+ /// Список ошибок
+ ///
+ public List Errors { get; }
+
+ ///
+ /// Значение
+ ///
+ public T? Value { get; set; }
+
+ #region Методы
+
+ #region Очистка
+ ///
+ /// Очищает список ошибок
+ ///
+ public void ClearErrors ()
+ {
+ Errors.Clear();
+ Errors.TrimExcess();
+ }
+
+ ///
+ /// Очищает список предупреждений
+ ///
+ public void ClearWarnings ()
+ {
+ Warnings.Clear();
+ Warnings.TrimExcess();
+ }
+
+ ///
+ /// Очищает список информации
+ ///
+ public void ClearInfo ()
+ {
+ Info.Clear();
+ Info.TrimExcess();
+ }
+
+ ///
+ /// Очищает все списки
+ ///
+ public void Clear ()
+ {
+ ClearInfo();
+ ClearWarnings();
+ ClearErrors();
+ }
+ #endregion
+
+ #region Добавление ошибки
+ ///
+ /// Добавление ошибки
+ ///
+ /// Ошибка
+ // ReSharper disable once MemberCanBeMadeStatic.Global
+ // ReSharper disable once FunctionRecursiveOnAllPaths
+ public void AddError (ActionError error) => Errors.Add(error);
+
+ ///
+ /// Добавляет ошибки в список
+ ///
+ /// Список ошибок
+ public void AddErrors(IEnumerable errors) => Errors.AddRange(errors);
+
+ ///
+ /// Добавление ошибки
+ ///
+ /// Является ли ошибка критической
+ public void AddError (bool critical = true)
+ {
+ //Создаю ошибку
+ ActionError error = new("", critical);
+
+ //Добавляю ошибку
+ AddError(error);
+ }
+
+ ///
+ /// Добавление ошибки
+ ///
+ /// Сообщение об ошибке
+ /// Является ли ошибка критической
+ public void AddError (string message, bool critical = true)
+ {
+ //Создаю ошибку
+ ActionError error = new(message, critical);
+
+ //Добавляю ошибку
+ AddError(error);
+ }
+
+ ///
+ /// Добавление ошибки
+ ///
+ /// Объект ошибки
+ /// Сообщение об ошибке
+ /// /// Является ли ошибка критической
+ public void AddError (string errorObject, string message, bool critical = true)
+ {
+ //Создаю ошибку
+ ActionError error = new(errorObject, message, critical);
+
+ //Добавляю ошибку
+ AddError(error);
+ }
+ #endregion
+
+ #region Добавление предупреждения
+ ///
+ /// Добавление предупреждения
+ ///
+ /// Предупреждение
+ public void AddWarning (ActionWarning warning) => Warnings.Add(warning);
+
+ ///
+ /// Добавление предупреждений
+ ///
+ /// Список предупреждений
+ public void AddWarnings(IEnumerable warnings) => Warnings.AddRange(warnings);
+
+ ///
+ /// Добавление предупреждение
+ ///
+ /// Текст предупреждения
+ /// Объект предупреждения
+ public void AddWarning (string message, string warningObject = "")
+ {
+ //Создаю предупреждение
+ ActionWarning warning = new(warningObject, message);
+
+ //Добавляю предупреждение
+ AddWarning(warning);
+ }
+ #endregion
+
+ #region Добавление информации
+ ///
+ /// Добавление информации
+ ///
+ /// Информация
+ public void AddInfo (ActionInfo info) => Info.Add(info);
+
+ ///
+ /// Добавление информации
+ ///
+ /// Список информации
+ public void AddInfos (IEnumerable infos) => Info.AddRange(infos);
+
+ ///
+ /// Добавление информации
+ ///
+ /// Текст информации
+ /// Объект информации
+ public void AddInfo (string message, string infoObject = "")
+ {
+ //Создаю информацию
+ ActionInfo info = new(infoObject, message);
+
+ //Добавляю информацию
+ AddInfo(info);
+ }
+ #endregion
+
+ #region Печать
+ ///
+ /// Печать списка ошибок
+ ///
+ /// Формат списка
+ /// Формат элемента списка
+ /// Список ошибок в текстовой форме
+ public string PrintErrorList (string formatList, string formatItem)
+ {
+ string elements =
+#pragma warning disable CS8625
+ Errors.Aggregate(null, (current, error) => current + error.PrintMessage(formatItem));
+#pragma warning restore CS8625
+
+ return string.Format(formatList, elements);
+ }
+
+ ///
+ /// Печать списка предупреждений
+ ///
+ /// Формат списка
+ /// Формат элемента списка
+ /// Список предупреждений в текстовой форме
+ public string PrintWarningList (string formatList, string formatItem)
+ {
+ string elements =
+#pragma warning disable CS8625
+ Warnings.Aggregate(null,
+#pragma warning restore CS8625
+ (current, warning) => current + warning.PrintMessage(formatItem));
+
+ return string.Format(formatList, elements);
+ }
+
+ ///
+ /// Печать списка информации
+ ///
+ /// Формат списка
+ /// Формат элемента списка
+ /// Список информации в текстовой форме
+ public string PrintInfoList (string formatList, string formatItem)
+ {
+ string elements =
+#pragma warning disable CS8625
+ Info.Aggregate(null, (current, info) => current + info.PrintMessage(formatItem));
+#pragma warning restore CS8625
+
+ return string.Format(formatList, elements);
+ }
+ #endregion
+
+ #region Проверка на наличие
+ ///
+ /// Проверяет, есть ли ошибки
+ ///
+ /// Игнорировать не критические
+ /// Наличие ошибок
+ public bool HasErrors (bool ignoreNonCritical = false) =>
+ ignoreNonCritical ? Errors.Any(static error => error.IsCritical) : Errors.Any();
+
+ ///
+ /// Проверяет, есть ли предупреждения
+ ///
+ /// Игнорировать информационные предупреждения
+ /// Наличие предупреждений
+ public bool HasWarnings (bool ignoreInformWarning = false) => ignoreInformWarning
+ ? Warnings.Any(static warning => !warning.IsInformWarning)
+ : Warnings.Any();
+
+ ///
+ /// Проверяет, есть ли сообщения
+ ///
+ /// Игнорировать статусные сообщения
+ /// Наличие сообщений
+ public bool HasInfo (bool ignoreStatus) => ignoreStatus ? Info.Any(static info => !info.IsStatusInfo) : Info.Any();
+
+ ///
+ /// Успешно ли завершилось
+ ///
+ public bool IsSuccess (bool ignoreNonCriticalErrors = false) =>
+ !HasErrors(ignoreNonCriticalErrors) && !HasWarnings(true);
+ #endregion
+
+ #region Количество сообщений
+ ///
+ /// Количество ошибок
+ ///
+ /// Игнорировать не критические
+ /// Количество ошибок
+ public int ErrorsCount (bool ignoreNonCritical = false) =>
+ ignoreNonCritical ? Errors.Count(static error => error.IsCritical) : Errors.Count;
+
+ ///
+ /// Количество предупреждений
+ ///
+ /// Игнорировать информационные предупреждения
+ /// Количество предупреждений
+ public int WarningsCount (bool ignoreInformWarning = false) => ignoreInformWarning
+ ? Warnings.Count(static warning => !warning.IsInformWarning)
+ : Warnings.Count;
+
+ ///
+ /// Количество информационных сообщений
+ ///
+ /// Игнорировать статусные сообщения
+ /// Количество информационных сообщений
+ public int InfoCount (bool ignoreStatus) => ignoreStatus ? Info.Count(static info => !info.IsStatusInfo) : Info.Count;
+ #endregion
+
+ #region Добавление другого состояния
+
+ ///
+ /// Добавляет другое состояние (например, результат другого действия, который возвращает ).
+ ///
+ /// Запись состояния
+ public void AddState(ActionState state)
+ {
+ AddErrors(state.Errors);
+ AddWarnings(state.Warnings);
+ AddInfos(state.Info);
+ }
+ #endregion
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/ActionStateSimply.cs b/anbs_cp/Classes/ActionStateSimply.cs
new file mode 100644
index 0000000..8c73d9d
--- /dev/null
+++ b/anbs_cp/Classes/ActionStateSimply.cs
@@ -0,0 +1,9 @@
+namespace anbs_cp.Classes;
+
+///
+/// Состояние действия
+///
+/// Обновлено 2023.11.1
+/// * Добавлен класс ActionState без возвращаемого значения
+///
+public sealed class ActionState: ActionState { }
\ No newline at end of file
diff --git a/anbs_cp/Classes/ActionWarning.cs b/anbs_cp/Classes/ActionWarning.cs
new file mode 100644
index 0000000..e25a6c7
--- /dev/null
+++ b/anbs_cp/Classes/ActionWarning.cs
@@ -0,0 +1,49 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс предупреждения
+///
+public sealed class ActionWarning: IActionWarning
+{
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public ActionWarning ()
+ {
+ IsInformWarning = false;
+ Object = string.Empty;
+ Message = string.Empty;
+ }
+
+ ///
+ /// Конструктор
+ ///
+ /// Объект
+ /// Сообщение
+ /// Является ли информирующим предупреждением
+ public ActionWarning (string eObject, string message, bool isInform = false)
+ {
+ IsInformWarning = isInform;
+ Object = eObject;
+ Message = message;
+ }
+ #endregion
+
+ #region Реализация интерфейса
+ ///
+ /// Объект
+ ///
+ public object Object { get; set; }
+ ///
+ /// Сообщение
+ ///
+ public string Message { get; set; }
+ ///
+ /// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию.
+ ///
+ public bool IsInformWarning { get; init; }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/ConsoleParamsParser.cs b/anbs_cp/Classes/ConsoleParamsParser.cs
new file mode 100644
index 0000000..f932b55
--- /dev/null
+++ b/anbs_cp/Classes/ConsoleParamsParser.cs
@@ -0,0 +1,61 @@
+namespace anbs_cp.Classes;
+
+///
+/// Обработчик параметров консоли
+///
+public sealed class ConsoleParamsParser
+{
+ ///
+ /// Массив параметров
+ ///
+ private readonly List<(string, string?)> _paramsList;
+
+ ///
+ /// Конструктор
+ ///
+ /// Параметры консоли
+ public ConsoleParamsParser (string[] consoleParams)
+ {
+ //Создаю список параметров
+ _paramsList = new();
+
+ //Заполняю его
+ foreach (string consoleParam in consoleParams)
+ {
+ //Индекс знака "="
+ int eqPlace = consoleParam.IndexOf('=');
+
+ //Получаю параметр
+ string param = eqPlace > -1 ? consoleParam[..eqPlace] : consoleParam;
+
+ //Получаю значение параметра
+ string? value = eqPlace == -1 ? null : consoleParam[(eqPlace + 1)..].Trim(new[] { '"' });
+
+ //Сохраняю в списке
+ _paramsList.Add((param.ToLower(), value));
+ }
+ }
+
+ ///
+ /// Проверяет наличие параметра
+ ///
+ /// Параметр
+ /// Есть ли параметр в списке
+ public bool HasParam (string param) =>
+ _paramsList.Any(keyValue => keyValue.Item1 == param.ToLower());
+
+ ///
+ /// Получает значение параметра
+ ///
+ ///
+ ///
+ public string? GetValue (string param) =>
+ !HasParam(param) ? null : _paramsList.FirstOrDefault(keyValue => keyValue.Item1 == param.ToLower()).Item2;
+
+ ///
+ /// Получает список всех параметров
+ ///
+ /// Список всех параметров
+ public List GetParamsList () =>
+ _paramsList.Select(static keyValue => keyValue.Item1.ToLower()).ToList();
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/CountConverter.cs b/anbs_cp/Classes/CountConverter.cs
new file mode 100644
index 0000000..662af0b
--- /dev/null
+++ b/anbs_cp/Classes/CountConverter.cs
@@ -0,0 +1,21 @@
+namespace anbs_cp.Classes;
+
+///
+/// Конвертер количества элементов
+///
+public sealed class CountConverter : ValueConverter
+{
+ ///
+ /// Имена размеров файлов по умолчанию
+ ///
+ public static readonly string[] DefaultNames = {"", "тыс.", "млн."};
+
+ ///
+ /// Конструктор класса
+ ///
+ /// Массив имён размерностей
+ /// Знаков после запятой (0, 1, 2)
+ public CountConverter (string[] valueNames, byte decimalPlace = 0) : base(valueNames, 1000, decimalPlace)
+ {
+ }
+}
diff --git a/anbs_cp/Classes/CountFormatter.cs b/anbs_cp/Classes/CountFormatter.cs
new file mode 100644
index 0000000..29774e0
--- /dev/null
+++ b/anbs_cp/Classes/CountFormatter.cs
@@ -0,0 +1,50 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Форматирует число элементов в понятную строку
+///
+public sealed class CountFormatter : IValueFormatter
+{
+ #region Cвойства класса
+
+ ///
+ /// Имена чисел (тысяч, миллионов, миллиардов и т.п.)
+ ///
+ public string[] CountNames { get; set; } = { "", "тыс.", "млн.", "млрд." };
+
+ ///
+ /// Знаков после запятой
+ ///
+ public byte DecimalPlaces { get; set; } = 1;
+
+ ///
+ /// Делители чисел
+ ///
+ public long[] Delimeters { get; set; } = { 1000, 1000000, 1000000000 };
+
+ #endregion
+
+ #region Реализация интерфейса
+
+ ///
+ /// Реализация интерфейса
+ ///
+ public string[] ValueNames
+ {
+ get => CountNames;
+ set => CountNames = value;
+ }
+
+ ///
+ /// Реализация интерфейса
+ ///
+ public long[] MaxSizes
+ {
+ get => Delimeters;
+ set => Delimeters = value;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/Encrypt/StringEncrypt.cs b/anbs_cp/Classes/Encrypt/StringEncrypt.cs
new file mode 100644
index 0000000..1a96540
--- /dev/null
+++ b/anbs_cp/Classes/Encrypt/StringEncrypt.cs
@@ -0,0 +1,37 @@
+namespace anbs_cp.Classes.Encrypt;
+
+///
+/// Статическая обертка для класса шифровки строк StringEncryptor
+///
+public static class StringEncrypt
+{
+ ///
+ /// Метод для шифрования строки
+ ///
+ /// Строка, которая должна быть зашифрована
+ /// Ключ
+ /// Этот статический метод возвращает зашифрованную строку
+ public static string Encrypt (string text, string key) => new StringEncryptor().Encrypt(text, key);
+
+ ///
+ /// Метод для дешифрования строки
+ ///
+ /// Строка, которая должна быть дешифрована
+ /// Ключ
+ /// Этот статический метод возвращает дешифрованную строку
+ public static string Decrypt (string text, string key) => new StringEncryptor().Decrypt(text, key);
+
+ ///
+ /// Декодирует зашифрованную строку в HTML-пригодный формат
+ ///
+ /// Зашифрованная строка
+ /// Этот статический метод возвращает дешифрованную строку
+ public static string Base64UrlEncode (string text) => new StringEncryptor().Base64UrlEncode(text);
+
+ ///
+ /// Раскодирует из декодированной строки в HTML-пригодный формат
+ ///
+ /// Декодированная строка
+ /// Этот статический метод возвращает шифрованную строку
+ public static string Base64UrlDecode (string text) => new StringEncryptor().Base64UrlDecode(text);
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/Encrypt/StringEncryptor.cs b/anbs_cp/Classes/Encrypt/StringEncryptor.cs
new file mode 100644
index 0000000..4f6cce8
--- /dev/null
+++ b/anbs_cp/Classes/Encrypt/StringEncryptor.cs
@@ -0,0 +1,127 @@
+using System.Security.Cryptography;
+using System.Text;
+
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes.Encrypt;
+
+///
+/// Класс для шифровки строк
+///
+public sealed class StringEncryptor: IEncryptor
+{
+ ///
+ /// Получение ключа из строки
+ ///
+ /// Ключ-строка
+ /// Хэш-ключ
+ /// Ключ
+ private static byte[] KeyFromString (string s, byte[] salt)
+ {
+ // Создаю хэшер
+ using Rfc2898DeriveBytes hasher = new(s, salt, 1000, HashAlgorithmName.SHA256);
+
+ // Получаю ключ
+ return hasher.GetBytes(32);
+ }
+
+ ///
+ /// Метод для шифрования строки
+ ///
+ /// Строка, которая должна быть зашифрована
+ /// Ключ
+ /// Этот метод возвращает зашифрованную строку
+ public string Encrypt (string value, string salt)
+ {
+ // Создаю криптограф
+ using Aes aes = Aes.Create();
+
+ // Получаю ключ
+ aes.Key = KeyFromString(salt, aes.IV);
+
+ // Открываю поток
+ using MemoryStream ms = new();
+
+ // Пишу данные в поток
+ ms.Write(aes.IV);
+
+ // Создаю шифрованный поток
+ using (CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write, true))
+ // Пишу данные в него
+ cs.Write(Encoding.UTF8.GetBytes(value));
+
+ // Возвращаю зашифрованный текст
+ return Convert.ToBase64String(ms.ToArray());
+ }
+
+ ///
+ /// Метод для дешифрования строки
+ ///
+ /// Строка, которая должна быть дешифрована
+ /// Ключ
+ /// Этот метод возвращает дешифрованную строку
+ public string Decrypt (string encryptedValue, string salt)
+ {
+ // Открываю поток в памяти
+ using MemoryStream ms = new(Convert.FromBase64String(encryptedValue));
+
+ // Задаю ключ
+ byte[] iv = new byte[16];
+
+ // Читаю его
+ _ = ms.Read(iv);
+
+ // Создаю криптограф
+ using Aes aes = Aes.Create();
+
+ // Получаю ключ
+ aes.Key = KeyFromString(salt, iv);
+
+ // присваиваю ключ
+ aes.IV = iv;
+
+ // Создаю поток дешифратора
+ using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read, true);
+
+ // Задаю поток итогового текста
+ using MemoryStream output = new();
+
+ // Копирую данные в выходной поток
+ cs.CopyTo(output);
+
+ // Вывожу расшифрованный текст
+ return Encoding.UTF8.GetString(output.ToArray());
+ }
+
+ ///
+ /// Декодирует зашифрованную строку в HTML-пригодный формат
+ ///
+ /// Зашифрованная строка
+ /// Этот метод возвращает дешифрованную строку
+ public string Base64UrlEncode (string text) => text.TrimEnd('=').Replace('+', '-').Replace('/', '_');
+
+ ///
+ /// Раскодирует из декодированной строки в HTML-пригодный формат
+ ///
+ /// Декодированная строка
+ /// Этот метод возвращает шифрованную строку
+ public string Base64UrlDecode (string text)
+ {
+ // Первоначальная замена
+ string result = text.Replace('_', '/').Replace('-', '+');
+
+ // Заменяю значения
+ switch (result.Length % 4)
+ {
+ case 2:
+ result += "==";
+ break;
+ case 3:
+ result += "=";
+ break;
+ }
+
+ // Возвращаю результат
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/Exceptions/RenameException.cs b/anbs_cp/Classes/Exceptions/RenameException.cs
new file mode 100644
index 0000000..e8eb5d5
--- /dev/null
+++ b/anbs_cp/Classes/Exceptions/RenameException.cs
@@ -0,0 +1,37 @@
+namespace anbs_cp.Classes.Exceptions;
+
+///
+/// Класс-исключение для переименования папок/файлов
+///
+public sealed class RenameException : Exception
+{
+ ///
+ /// Имя файла/папки
+ ///
+ public string FileName { get; }
+
+ ///
+ /// Описание ошибки
+ ///
+ public string? ErrorMessage { get; }
+
+ ///
+ /// Конструктор
+ ///
+ /// Имя файла/папки
+ /// Описание ошибки
+ public RenameException(string fileName, string? errorMessage) : base(GetMessage(fileName, errorMessage ?? string.Empty))
+ {
+ FileName = fileName;
+ ErrorMessage = errorMessage;
+ }
+
+ ///
+ /// Получение текстового представление ошибки
+ ///
+ /// Имя файла/папки
+ /// Описание ошибки
+ /// Текстовое представление ошибки
+ private static string GetMessage(string fileName, string errorMessage) =>
+ $"При переименовании файла/папки {fileName} возникла следующая ошибка: {errorMessage}";
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/FileExtensions.cs b/anbs_cp/Classes/FileExtensions.cs
new file mode 100644
index 0000000..2988845
--- /dev/null
+++ b/anbs_cp/Classes/FileExtensions.cs
@@ -0,0 +1,27 @@
+namespace anbs_cp.Classes;
+
+///
+/// Класс -- расширение для класса File
+///
+public static class FileExtension
+{
+ ///
+ /// Получает MIME-тип файла
+ ///
+ /// Имя файла
+ /// MIME-тип файла
+ public static string MIMEType (string filename) =>
+ MimeTypes.GetMimeType(filename);
+
+ ///
+ /// Размер файла в байтах
+ ///
+ /// Полное имя и путь к файлу
+ /// Размер файла в байтах
+ public static long FileSize(string fileName)
+ {
+ FileInfo fileInfo = new (fileName);
+
+ return fileInfo.Length;
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/FileHash.cs b/anbs_cp/Classes/FileHash.cs
new file mode 100644
index 0000000..72b09da
--- /dev/null
+++ b/anbs_cp/Classes/FileHash.cs
@@ -0,0 +1,52 @@
+using System.Security.Cryptography;
+using System.Text;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс для работы с хэшем файла
+///
+public sealed class FileHash
+{
+ ///
+ /// Получение md5-хэша файла.
+ /// Взято с https://stackoverflow.com/a/24031467/16469671
+ ///
+ /// Имя файла
+ /// Массив хэша
+ public FileHash (string fileName)
+ {
+ using MD5 md5 = MD5.Create();
+ using FileStream stream = File.OpenRead(fileName);
+ Hash = md5.ComputeHash(stream);
+ }
+
+ ///
+ /// Простой конструктор
+ ///
+ public FileHash ()
+ {
+ Hash = new byte[] { };
+ }
+
+ ///
+ /// Хэш файла
+ ///
+ public byte[] Hash { get; private set; }
+
+ ///
+ /// Вывод в строку
+ ///
+ /// Строка хэша файла
+ public override string ToString () => BitConverter.ToString(Hash).Replace("-", "").ToLowerInvariant();
+
+ ///
+ /// Конвертирует строку в хэш
+ ///
+ /// Строка
+ public void FromString (string value)
+ {
+ UTF8Encoding utf8 = new();
+ Hash = utf8.GetBytes(value);
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/FileSizeConverter.cs b/anbs_cp/Classes/FileSizeConverter.cs
new file mode 100644
index 0000000..5aa77ec
--- /dev/null
+++ b/anbs_cp/Classes/FileSizeConverter.cs
@@ -0,0 +1,21 @@
+namespace anbs_cp.Classes;
+
+///
+/// Конвертер размеров файлов
+///
+public sealed class FileSizeConverter : ValueConverter
+{
+ ///
+ /// Имена размеров файлов по умолчанию
+ ///
+ public static readonly string[] DefaultNames = {"байт", "Кб", "Мб", "Гб", "Тб"};
+
+ ///
+ /// Конструктор класса
+ ///
+ /// Массив имён размерностей
+ /// Знаков после запятой (0, 1, 2)
+ public FileSizeConverter (string[] valueNames, byte decimalPlace = 2) : base(valueNames, 1024, decimalPlace)
+ {
+ }
+}
diff --git a/anbs_cp/Classes/FileSizeFormatter.cs b/anbs_cp/Classes/FileSizeFormatter.cs
new file mode 100644
index 0000000..b3e2891
--- /dev/null
+++ b/anbs_cp/Classes/FileSizeFormatter.cs
@@ -0,0 +1,71 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Форматирует размер файла/папки в понятную строку
+///
+public class FileSizeFormatter : IValueFormatter
+{
+ #region Cвойства класса
+
+ ///
+ /// Имена размеров (байт, килобайт, мегабайт, гигабайт и террабайт)
+ ///
+ public string[] SizeNames { get; set; } = { "Байт", "Кб", "Мб", "Гб", "Тб" };
+
+ ///
+ /// Знаков после запятой
+ ///
+ public byte DecimalPlaces { get; set; } = 2;
+
+ ///
+ /// Максимально байт (далее идут Кбайты)
+ ///
+ public long ByteMax { get; set; } = 1024;
+
+ ///
+ /// Максимально Кбайт (далее идут Мбайты)
+ ///
+ public long KByteMax { get; set; } = 1048576;
+
+ ///
+ /// Максимально Мбайт (далее идут Гбайты)
+ ///
+ public long MByteMax { get; set; } = 1073741824;
+
+ ///
+ /// Максимально Гбайт (далее идут Тбайты)
+ ///
+ public long GByteMax { get; set; } = 1099511627776;
+
+ #endregion
+
+ #region Реализация интерфейса
+
+ ///
+ /// Реализация интерфейса
+ ///
+ public string[] ValueNames
+ {
+ get => SizeNames;
+ set => SizeNames = value;
+ }
+
+ ///
+ /// Реализация интерфейса
+ ///
+ public long[] MaxSizes
+ {
+ get => new[] { ByteMax, KByteMax, MByteMax, GByteMax };
+ set
+ {
+ ByteMax = value[0];
+ KByteMax = value[1];
+ MByteMax = value[2];
+ GByteMax = value[3];
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/KeyValueList.cs b/anbs_cp/Classes/KeyValueList.cs
new file mode 100644
index 0000000..f9e0810
--- /dev/null
+++ b/anbs_cp/Classes/KeyValueList.cs
@@ -0,0 +1,163 @@
+using System.Collections;
+
+using anbs_cp.Structs;
+
+namespace anbs_cp.Classes;
+
+///
+/// Список из пара ключ-значение
+///
+/// Тип ключа
+/// Тип значения
+public class KeyValueList: IEnumerable>
+{
+ ///
+ /// Хранение значений
+ ///
+ private readonly List> _list;
+
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public KeyValueList () => _list = new();
+ #endregion
+
+ #region Свойства
+ ///
+ /// Список ключей из списка
+ ///
+ public IEnumerable Keys => GetKeys();
+ #endregion
+
+ #region Методы
+
+ ///
+ /// Получает список ключей
+ ///
+ /// Список ключей
+ private IEnumerable GetKeys () => from keyValue in _list where keyValue.Key is not null select keyValue.Key;
+
+ ///
+ /// Добавляет в список параметр
+ ///
+ /// Параметр
+ public void Add (KeyValue keyValue) => _list.Add(keyValue);
+
+ ///
+ /// Добавляет в список параметр
+ ///
+ /// Ключ параметра
+ /// Значение
+ public void Add (TK key, TV value) => _list.Add(new(key, value));
+
+ ///
+ /// Изменяет значение
+ ///
+ /// Новое значение
+ public void ChangeValue (KeyValue keyValue)
+ {
+ // Если такой ключ не существует
+ if (!Contains(keyValue.Key!))
+ {
+ // - тогда добавляю новое значение
+ Add(keyValue);
+
+ // - прерываю
+ return;
+ }
+
+ // Существующее значение
+ KeyValue existValue = GetItem(keyValue.Key!) ?? new();
+
+ // Удаляем существующее
+ _list.Remove(existValue);
+
+ // Добавляем новое
+ _list.Add(keyValue);
+ }
+
+ ///
+ /// Изменяет значение
+ ///
+ /// Ключ
+ /// Новое значение
+ public void ChangeValue (TK key, TV newValue) => ChangeValue(new(key, newValue));
+
+ ///
+ /// Получает элемент по ключу
+ ///
+ /// Ключ
+ /// Элемент
+ public KeyValue? GetItem (TK key)
+ {
+ // Ищем элемент в списке
+ foreach (KeyValue keyValueItem in _list.Where(keyValueItem => keyValueItem.Key!.Equals(key)))
+ // - возвращаем его при нахождении
+ return keyValueItem;
+
+ // Элемент не найден -- вывожу null
+ return null;
+ }
+
+ ///
+ /// Получает значение
+ ///
+ /// Ключ
+ /// Значение
+ public TV? GetValue (TK key)
+ {
+ // Если такой ключ не существует
+ if (!Contains(key))
+ // Тогда возвращаю значение по умолчанию
+ return default;
+
+ // Получаю элемент
+ KeyValue keyValue = GetItem(key) ?? new();
+
+ // Вывожу значение
+ return keyValue.Value;
+ }
+
+ ///
+ /// Удаляет элемент из списка
+ ///
+ /// Элемент
+ public void Remove (KeyValue keyValue) => _list.Remove(keyValue);
+
+ ///
+ /// Удаляет элемент из списка
+ ///
+ /// Ключ элемента
+ public void Remove (TK key) => Remove(GetItem(key) ?? new());
+
+ ///
+ /// Проверяет, содержится ли элемент в списке
+ ///
+ /// Элемент
+ /// Результат проверки
+ public bool Contains (KeyValue keyValue) => _list.Contains(keyValue);
+
+ ///
+ /// Проверяет, содержится ли элемент в списке
+ ///
+ /// Ключ элемента
+ /// Результат проверки
+ public bool Contains (TK key) => Keys.Any(keyParam => keyParam!.Equals(key));
+
+ #endregion
+
+ #region Реализация интерфейса IEnumerable>
+ ///
+ /// Получаю
+ ///
+ ///
+ public IEnumerator> GetEnumerator () => _list.GetEnumerator();
+
+ ///
+ /// Получаю
+ ///
+ ///
+ IEnumerator IEnumerable.GetEnumerator () => GetEnumerator();
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/LikeDelphi.cs b/anbs_cp/Classes/LikeDelphi.cs
new file mode 100644
index 0000000..09a8afc
--- /dev/null
+++ b/anbs_cp/Classes/LikeDelphi.cs
@@ -0,0 +1,147 @@
+using anbs_cp.Classes.Exceptions;
+using anbs_cp.Enums;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс, добавляющий реализацию некоторых методов Delphi, которые упрощают работу в C#.
+///
+public static class LikeDelphi
+{
+ ///
+ /// Аналог функции IncludeTrailingBackslash
+ ///
+ /// Путь, к которому нужно добавить slash
+ /// Путь со slash в конце
+ public static string IncludeTrailingBackslash (string path)
+ {
+ //По умолчанию сохраняем путь
+ string result = path;
+
+ //Если последний символ не "\", то добавим "\" в конце
+ if (path[^1] != '\\')
+ result = $@"{path}\";
+
+ //Вернём результат
+ return result;
+ }
+
+ ///
+ /// Парсер строки в множество строк
+ ///
+ /// Строка, которую нужно разбить
+ /// Символ-делитель строки
+ /// Массив строк
+ public static List ParseString (string str, char delimiter) => str.Split(delimiter).ToList();
+
+ ///
+ /// Переименовываю файл
+ ///
+ /// Старое имя файла (с полным путём)
+ /// Новое имя файла (с полным путём)
+ /// Что делать, если существует
+ /// Если имеет значение RaiseException, то генерируется ошибка переименования файла
+ public static void RenameFile (string oldName, string newName,
+ EOnExistAction ifExist = EOnExistAction.RaiseException)
+ {
+ //Если целевой файл существует
+ if (File.Exists(newName))
+ switch (ifExist)
+ {
+ //Возбуждать исключение
+ case EOnExistAction.RaiseException:
+ throw new RenameException(newName, "Файл уже существует!");
+ //Прерываю
+ case EOnExistAction.Abort:
+ return;
+ //Игнорирую и перезаписываю файл
+ case EOnExistAction.Ignore:
+ break;
+ //Только для папок (для файлов равносилен RaiseException)
+ case EOnExistAction.RaiseExceptionIfNotEmpty:
+ throw new RenameException(newName, "Файл уже существует!");
+ //Только для папок (для файлов равносилен Abort)
+ case EOnExistAction.AbortIfNotEmpty:
+ return;
+ //по умолчанию - RaiseException
+ default:
+ throw new RenameException(newName, "Файл уже существует!");
+ }
+
+ //Перемещаю файл
+ File.Move(oldName, newName, true);
+
+ //Если начальный файл существует
+ if (File.Exists(oldName))
+ //- удаляю его
+ File.Delete(oldName);
+ }
+
+ ///
+ /// Удаление папки
+ ///
+ /// Папка
+ public static void RemoveDir (string dir) => Directory.Delete(dir, true);
+
+ ///
+ /// Проверяет папку на пустоту
+ /// Оригинальный ответ от OwenGlendower (https://www.cyberforum.ru/windows-forms/thread1995240.html)
+ ///
+ /// Проверяемая папка
+ /// Пуста (true) или не пуста (false) папка
+ public static bool IsDirEmpty (string dir) => !Directory.EnumerateFiles(dir, "*.*", SearchOption.AllDirectories).Any();
+
+ ///
+ /// Переименовывает папку
+ ///
+ /// Старое имя папки (с полным путём)
+ /// Новое имя папки (с полным путём)
+ /// Что делать, если существует
+ /// Если имеет значение RaiseException, то генерируется ошибка переименования папки
+ public static void RenameDir (string oldName, string newName,
+ EOnExistAction ifExist = EOnExistAction.RaiseException)
+ {
+ //Если целевая папка существует
+ if (Directory.Exists(newName))
+ {
+ switch (ifExist)
+ {
+ //Возбуждать исключение
+ case EOnExistAction.RaiseException:
+ throw new RenameException(newName, "Папка уже существует!");
+ //Прерывать
+ case EOnExistAction.Abort:
+ return;
+ //Игнорировать и перезаписывать папку
+ case EOnExistAction.Ignore:
+ break;
+ //Возбуждать исключение, если не пустая
+ case EOnExistAction.RaiseExceptionIfNotEmpty:
+ if (!IsDirEmpty(newName))
+ throw new RenameException(newName, "Папка уже существует и не пуста!");
+
+ break;
+ //Прерывать, если не пустая
+ case EOnExistAction.AbortIfNotEmpty:
+ if (!IsDirEmpty(newName))
+ return;
+
+ break;
+ //по умолчанию - RaiseException
+ default:
+ throw new RenameException(newName, "Папка уже существует!");
+ }
+
+ //Удаляю целевую папку
+ RemoveDir(newName);
+ }
+
+ //Перемещаю папку
+ Directory.Move(oldName, newName);
+
+ //Если начальная папка существует
+ if (Directory.Exists(oldName))
+ //- удаляю его
+ RemoveDir(oldName);
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/PasswordOptions.cs b/anbs_cp/Classes/PasswordOptions.cs
new file mode 100644
index 0000000..519f5de
--- /dev/null
+++ b/anbs_cp/Classes/PasswordOptions.cs
@@ -0,0 +1,50 @@
+namespace anbs_cp.Classes;
+
+///
+/// Параметры пароля
+///
+public sealed class PasswordOptions
+{
+ ///
+ /// Конструктор
+ ///
+ public PasswordOptions ()
+ {
+ RequiredLength = 8;
+ RequireLowercase = true;
+ RequireUppercase = true;
+ RequireDigit = true;
+ RequireNonAlphanumeric = false;
+ RequiredUniqueChars = 6;
+ }
+
+ ///
+ /// Требуемая длина пароля
+ ///
+ public byte RequiredLength { get; set; }
+
+ ///
+ /// Требовать строчные буквы в пароле
+ ///
+ public bool RequireLowercase { get; set; }
+
+ ///
+ /// Требовать прописные буквы в пароле
+ ///
+ public bool RequireUppercase { get; set; }
+
+ ///
+ /// Требовать цифры в пароле
+ ///
+ public bool RequireDigit { get; set; }
+
+ ///
+ /// Требовать символы
+ ///
+ public bool RequireNonAlphanumeric { get; set; }
+
+ ///
+ /// Уникальных символов
+ ///
+ public byte RequiredUniqueChars { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/SimpleMapper.cs b/anbs_cp/Classes/SimpleMapper.cs
new file mode 100644
index 0000000..6195d0f
--- /dev/null
+++ b/anbs_cp/Classes/SimpleMapper.cs
@@ -0,0 +1,133 @@
+using System.Reflection;
+
+namespace anbs_cp.Classes;
+
+///
+/// Класс перевода одинаковых свойств из класса TF в класс T.
+/// Оригинальные автор(-ы): keenthinker и Avtandil Kavrelishvili.
+/// Улучшения: А. Н. Бабаев
+/// URL: https://stackoverflow.com/questions/20410234/how-to-automatically-map-the-values-between-instances-of-two-different-classes-i
+///
+public static class SimpleMapper
+{
+ ///
+ /// Перевод одинаковых свойств из класса F в класс TT.
+ ///
+ /// Экземпляр класса F
+ /// Ссылка на экземпляр класса T
+ /// Тип сопоставления
+ /// Список параметров для сопоставления
+ /// Класс-родитель
+ /// Класс-приемник
+ public static void MapEx(TF from, ref T to, MapMode mode, List list)
+ {
+ //Копирую поля
+ Type typeOfA = typeof(TF);
+ Type typeOfB = typeof(T);
+ foreach (FieldInfo fieldOfA in typeOfA.GetFields())
+ {
+ //Проверяем выполнение условия и прерываем, если не выполняется
+ if (!CheckCondition(fieldOfA.Name, fieldOfA.GetValue(from), mode, list))
+ continue;
+
+ //Получаем FieldInfo для b по имени поля a
+ FieldInfo? fieldOfB = typeOfB.GetField(fieldOfA.Name);
+
+ //Присваиваю поля типа B значение поля типа A
+ fieldOfB?.SetValue(to, fieldOfA.GetValue(from));
+ }
+
+ //Копирую свойства
+ foreach (PropertyInfo propertyOfA in typeOfA.GetProperties())
+ {
+ //Проверяем выполнение условия и прерываем, если не выполняется
+ if (!CheckCondition(propertyOfA.Name, propertyOfA.GetValue(from), mode, list))
+ continue;
+
+ //Получаем PropertyInfo для b по имени свойства a
+ PropertyInfo? propertyOfB = typeOfB.GetProperty(propertyOfA.Name);
+ //Присваиваю свойству типа B значение свойства типа A
+ propertyOfB?.SetValue(to, propertyOfA.GetValue(from));
+ }
+ }
+
+ ///
+ /// Перевод одинаковых свойств из класса F в класс TT (режим "сопоставление всех параметров").
+ ///
+ /// Параметр класса F
+ /// Класс-родитель
+ /// Класс-приемник
+ /// Элемент класса T
+ public static T Map(TF from)
+ {
+ //Создаю элемент
+ // ReSharper disable once NullableWarningSuppressionIsUsed
+ T result = (T)Activator.CreateInstance(typeof(T))!;
+ //Сопоставляю по принципу "сопоставление всех параметров"
+ MapEx(from, ref result, MapMode.MapFull, new());
+ //Вывожу в результат
+ return result;
+ }
+
+ ///
+ /// Проверка выполнения условия
+ ///
+ /// Имя элемента
+ /// Значение элемента
+ /// Режим проверки
+ /// Список игнорирования/добавления
+ ///
+ private static bool CheckCondition(string itemName, object? itemValue, MapMode mode, ICollection list)
+ {
+ //Если режим "Только список" и поля нет в списке,
+ //либо режим "Только не в списке" и поле есть в списке
+ //или режим "Только не пустые" и значение поля пустое,
+ //или режим "Только не по умолчанию" и значение по умолчанию
+ //то пропускаем
+ bool result =
+ mode switch
+ {
+ MapMode.MapFull => true,
+ MapMode.MapNotNull => itemValue != null,
+ MapMode.MapByList => list.Contains(itemName),
+ MapMode.MapIgnoreList => !list.Contains(itemName),
+ MapMode.MapNotDefault => itemValue != default,
+ MapMode.MapNotNullOrDefault => !Equals(itemValue, default(T)),
+ _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null)
+ };
+
+ //Возвращаем результат
+ return result;
+ }
+
+ ///
+ /// Перечисление типов сопоставления
+ ///
+ public enum MapMode
+ {
+ ///
+ /// Сопоставление всех параметров
+ ///
+ MapFull = 0,
+ ///
+ /// Сопоставление не пустых параметров
+ ///
+ MapNotNull = 1,
+ ///
+ /// Сопоставление по списку
+ ///
+ MapByList = 2,
+ ///
+ /// Сопоставление исключая список
+ ///
+ MapIgnoreList = 3,
+ ///
+ /// Сопоставление параметров, которые не равны значению по умолчанию
+ ///
+ MapNotDefault = 4,
+ ///
+ /// Сопоставление не пустых параметров, которые не равны значению по умолчанию (NotNull и NotDefault одновременно)
+ ///
+ MapNotNullOrDefault = 5,
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/TextFormatter.cs b/anbs_cp/Classes/TextFormatter.cs
new file mode 100644
index 0000000..470fa0e
--- /dev/null
+++ b/anbs_cp/Classes/TextFormatter.cs
@@ -0,0 +1,128 @@
+using System.Net.Mail;
+using System.Text.RegularExpressions;
+
+namespace anbs_cp.Classes;
+
+///
+/// Форматирование текста
+///
+public static class TextFormatter
+{
+ ///
+ /// Заменяет %МАРКЕРЫ% на их значения
+ ///
+ /// Текст сообщения
+ /// Словарь замен
+ /// Отформатированное сообщение
+ public static string FormatMessage (string message, Dictionary replaceDictionary) =>
+ replaceDictionary.Aggregate(message,
+ static (current, item) => current.Replace($"%{item.Key}%", item.Value));
+
+ ///
+ /// Обрезает строку до указанных в параметре символов
+ ///
+ /// Текст, который нужно обрезать
+ /// Максимальное количество символов в тексте
+ /// Чем завершать обрезанный текст, если он был обрезан. Внимание расходует !
+ /// Обрезанный текст
+ public static string GetShortText (string text, int maxLength, string endDots = "") =>
+ text.Length < maxLength ? text : $"{text[..(maxLength - endDots.Length)]}{endDots}";
+
+ ///
+ /// Генерирует случайный пароль, удовлетворяющий параметрам .
+ /// Автор метода: Darkseal (https://stackoverflow.com/users/1233379/darkseal)
+ /// URL: https://stackoverflow.com/a/46229180/16469671
+ ///
+ /// Объект допустимых параметров пароля, содержащий требования к надежности пароля.
+ /// Случайный пароль
+ public static string GenerateRandomPassword (PasswordOptions? options)
+ {
+ //Проверка options и установка по-умолчанию
+ options ??= new();
+
+ //Получаю массив символов
+ string[] randomChars = {
+ "ABCDEFGHJKLMNOPQRSTUVWXYZ", // прописные буквы
+ "abcdefghijkmnopqrstuvwxyz", // строчные буквы
+ "0123456789", // цифры
+ "~!@#$%^&*+-/.,{}[]();:|?<>='`" // символы
+ };
+
+ //Создаю объект Random
+ Random rand = new(Environment.TickCount);
+
+ //Массив результатов
+ List chars = new();
+
+ //Вставляю прописные буквы
+ if (options.RequireUppercase)
+ chars.Insert(rand.Next(0, chars.Count),
+ randomChars[0][rand.Next(0, randomChars[0].Length)]);
+
+ //Вставляю строчные буквы
+ if (options.RequireLowercase)
+ chars.Insert(rand.Next(0, chars.Count),
+ randomChars[1][rand.Next(0, randomChars[1].Length)]);
+
+ //Вставляю цифры
+ if (options.RequireDigit)
+ chars.Insert(rand.Next(0, chars.Count),
+ randomChars[2][rand.Next(0, randomChars[2].Length)]);
+
+ //Вставляю символы
+ if (options.RequireNonAlphanumeric)
+ chars.Insert(rand.Next(0, chars.Count),
+ randomChars[3][rand.Next(0, randomChars[3].Length)]);
+
+ //Делаю выборку
+ for (int i = chars.Count; i < options.RequiredLength || chars.Distinct().Count() < options.RequiredUniqueChars; i++)
+ {
+ string rcs = randomChars[rand.Next(0, randomChars.Length)];
+ chars.Insert(rand.Next(0, chars.Count),
+ rcs[rand.Next(0, rcs.Length)]);
+ }
+
+ //Вывожу результат
+ return new(chars.ToArray());
+ }
+
+ ///
+ /// Проверяет на соответствие критерию электронной почты
+ /// Взято с: https://stackoverflow.com/a/1374644/16469671
+ ///
+ /// Проверяемая строка
+ /// Является ли адресом электронной почты
+ public static bool IsValidEmail (string email)
+ {
+ string trimmedEmail = email.Trim();
+
+ if (trimmedEmail.EndsWith(".", StringComparison.Ordinal))
+ return false;
+
+ try
+ {
+ MailAddress addr = new(email);
+ return addr.Address == trimmedEmail;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Проверяет текст на совпадение регулярному выражению по шаблону с опциями (см. )
+ ///
+ /// Текст на проверку
+ /// Шаблон
+ /// Параметры проверки в формате (можно игнорировать, по умолчанию: )
+ /// Есть ли совпадения в тексте
+ public static bool IsMatchRegExp (string text, string pattern, RegexOptions? options = null)
+ {
+ // Задаю настройки проверки регулярных выражений
+ RegexOptions regexOptions = options ?? RegexOptions.IgnoreCase;
+
+ // Возвращаю результат
+ return Regex.IsMatch(text, pattern, regexOptions);
+ }
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/TimestampValidator.cs b/anbs_cp/Classes/TimestampValidator.cs
new file mode 100644
index 0000000..c85266a
--- /dev/null
+++ b/anbs_cp/Classes/TimestampValidator.cs
@@ -0,0 +1,90 @@
+namespace anbs_cp.Classes;
+
+///
+/// Класс проверки временного интервала
+///
+public static class TimestampValidator
+{
+ ///
+ /// Проверка попадания в заданный интервал (в мс)
+ ///
+ /// Временной интервал
+ /// Проверяемый временной интервал
+ /// Временная дельта в миллисекундах
+ ///
+ /// Попал ли в промежуток +
+ ///
+ ///
+ public static bool Validate(long timestamp, long checkedStamp, ulong deltaMs) =>
+ new TimeSpan(timestamp) + TimeSpan.FromMilliseconds(deltaMs) > new TimeSpan(checkedStamp);
+
+ ///
+ /// Проверка попадания текущего времени в заданный интервал (в мс)
+ ///
+ /// Временной интервал
+ /// Временная дельта в миллисекундах
+ /// Попадает ли текущее время в промежуток +
+ public static bool ValidateNow(long timestamp, ulong deltams) =>
+ Validate(timestamp, DateTime.UtcNow.Ticks, deltams);
+
+ ///
+ /// Проверка временного интервала (в сек)
+ ///
+ /// Временной интервал
+ /// Проверяемый временной интервал
+ /// Временная дельта в секундах
+ /// Попал ли в промежуток
+ public static bool ValidateFromSec(long timestamp, long checkedstamp, ulong deltasec) =>
+ Validate(timestamp, checkedstamp, checked(deltasec * 1000UL));
+
+ ///
+ /// Проверка попадания текущего времени в заданный интервал (в сек)
+ ///
+ /// Временной интервал
+ /// Временная дельта в секундах
+ /// Попадает ли текущее время в промежуток +
+ public static bool ValidateFromSecNow(long timestamp, ulong deltasec) =>
+ ValidateFromSec(timestamp, DateTime.UtcNow.Ticks, deltasec);
+
+ ///
+ /// Проверка временного интервала (в мин)
+ ///
+ /// Временной интервал
+ /// Проверяемый временной интервал
+ /// Временная дельта в минутах
+ ///
+ /// Попал ли в промежуток +
+ ///
+ public static bool ValidateFromMin(long timestamp, long checkedstamp, ulong deltamin) =>
+ Validate(timestamp, checkedstamp, checked(deltamin * 60000UL));
+
+ ///
+ /// Проверка попадания текущего времени в заданный интервал (в мин)
+ ///
+ /// Временной интервал
+ /// Временная дельта в минутах
+ /// Попадает ли текущее время в промежуток +
+ public static bool ValidateFromMinNow(long timestamp, ulong deltamin) =>
+ ValidateFromMin(timestamp, DateTime.UtcNow.Ticks, deltamin);
+
+ ///
+ /// Проверка временного интервала (в час)
+ ///
+ /// Временной интервал
+ /// Проверяемый временной интервал
+ /// Временная дельта в часах
+ ///
+ /// Попал ли в промежуток +
+ ///
+ public static bool ValidateFromHour(long timestamp, long checkedStamp, ulong deltaHour) =>
+ Validate(timestamp, checkedStamp, checked(deltaHour * 3600000UL));
+
+ ///
+ /// Проверка попадания текущего времени в заданный интервал (в час)
+ ///
+ /// Временной интервал
+ /// Временная дельта в часах
+ /// Попадает ли текущее время в промежуток +
+ public static bool ValidateFromHourNow(long timestamp, ulong deltahr) =>
+ ValidateFromHour(timestamp, DateTime.UtcNow.Ticks, deltahr);
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/TypeConverter.cs b/anbs_cp/Classes/TypeConverter.cs
new file mode 100644
index 0000000..06c88d3
--- /dev/null
+++ b/anbs_cp/Classes/TypeConverter.cs
@@ -0,0 +1,165 @@
+using System.Globalization;
+
+using Newtonsoft.Json;
+
+namespace anbs_cp.Classes;
+
+///
+/// Конвертер типов на манер Delphi
+///
+public static class TypeConverter
+{
+ #region Конвертация числа в строку
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string IntToStr (int value) => value.ToString();
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string IntToStr (uint value) => value.ToString();
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string IntToStr (long value) => value.ToString();
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string IntToStr (ulong value) => value.ToString();
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string IntToStr (byte value) => value.ToString();
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string DecimalToStr (decimal value) => value.ToString(CultureInfo.InvariantCulture);
+
+ ///
+ /// Преобразование в
+ ///
+ /// Число
+ /// Значение в
+ public static string DoubleToStr (double value) => value.ToString(CultureInfo.InvariantCulture);
+
+ ///
+ /// Преобразование в
+ ///
+ /// Значение правда/ложь
+ /// Значение в
+ public static string BoolToStr (bool value) => value.ToString();
+
+ ///
+ /// Преобразование любого типа в (сериализация)
+ ///
+ /// Тип
+ /// Значение типа
+ /// Значение в
+ public static string TypeToStr (T value) => JsonConvert.SerializeObject(value);
+
+ #endregion
+
+ #region Конвертация строки в число
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static int StrToInt (string value, int defaultValue = 0) =>
+ int.TryParse(value, out int result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static uint StrToUInt (string value, uint defaultValue = 0) =>
+ uint.TryParse(value, out uint result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static long StrToInt64 (string value, long defaultValue = 0) =>
+ long.TryParse(value, out long result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static ulong StrToUInt64 (string value, ulong defaultValue = 0) =>
+ ulong.TryParse(value, out ulong result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static byte StrToByte (string value, byte defaultValue = byte.MinValue) =>
+ byte.TryParse(value, out byte result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию ()
+ /// Значение в
+ public static decimal StrToDecimal (string value, decimal defaultValue = decimal.Zero) =>
+ decimal.TryParse(value, out decimal result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static double StrToDouble (string value, double defaultValue = 0) =>
+ double.TryParse(value, out double result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в
+ ///
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static bool StrToBool (string value, bool defaultValue = false) =>
+ bool.TryParse(value, out bool result) ? result : defaultValue;
+
+ ///
+ /// Преобразование в тип (десериализация)
+ ///
+ /// Тип
+ /// Строка
+ /// Значение по умолчанию
+ /// Значение в
+ public static T StrToType(string value, T defaultValue) =>
+ JsonConvert.DeserializeObject(value) ?? defaultValue;
+
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Classes/ValueConverter.cs b/anbs_cp/Classes/ValueConverter.cs
new file mode 100644
index 0000000..ca89b23
--- /dev/null
+++ b/anbs_cp/Classes/ValueConverter.cs
@@ -0,0 +1,87 @@
+using anbs_cp.Interfaces;
+
+namespace anbs_cp.Classes;
+
+///
+/// Абстрактный класс конвертера величин для отображения (улучшенный аналог ValueFormatter)
+///
+public abstract class ValueConverter: IValueConverter
+{
+ ///
+ /// Конструктор
+ ///
+ /// Массив имён размерностей
+ /// Делитель
+ /// Число знаков после запятой
+ protected ValueConverter (string[] valueNames, long divider, byte decimalPlaces)
+ {
+ ValueNames = valueNames;
+ Divider = divider;
+ DecimalPlaces = (byte)(decimalPlaces < 3 ? decimalPlaces : 2);
+ }
+
+ #region Реализация интерфейса
+ ///
+ /// Массив имён размерностей
+ ///
+ public string[] ValueNames { get; init; }
+
+ ///
+ /// Делитель
+ ///
+ public long Divider { get; init; }
+
+ ///
+ /// Знаков после запятой (0, 1, 2)
+ ///
+ public byte DecimalPlaces { get; init; }
+
+ #endregion
+
+ #region Методы
+ ///
+ /// Функция конвертирования в строку
+ ///
+ /// Значение
+ /// Конвертирование значение в строку
+ public string Convert (long value)
+ {
+ //Получаю разделенное значение
+ (decimal, int) result = DivideIt(value, 0);
+
+ //Преобразую значение в строку
+ string resultValue = DecimalPlaces switch {
+ 0 => $"{result.Item1:F0}",
+ 1 => $"{result.Item1:F1}",
+ _ => $"{result.Item1:F2}"
+ };
+
+ //Возвращаю результат
+ return $"{resultValue} {ValueNames[result.Item2]}";
+ }
+
+
+ ///
+ /// Рекурсивная функция деления
+ ///
+ /// Число
+ /// Счётчик вызова рекурсии
+ /// Число в остатке и количество вызовов рекурсии
+ private (decimal, int) DivideIt (decimal value, int count)
+ {
+ //Если счёт уже больше количества названий
+ if (count > ValueNames.Length)
+ return (value, count);
+
+ //Если частное уже меньше делителя, то прерываем цикл
+ if (value < Divider)
+ return (value, count);
+
+ //Увеличиваем счётчик...
+ count++;
+
+ //... и продолжаем цикл
+ return DivideIt(value / Divider, count);
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/CountFormatter.cs b/anbs_cp/CountFormatter.cs
deleted file mode 100644
index 05bba3a..0000000
--- a/anbs_cp/CountFormatter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-namespace anbs_cp
-{
- ///
- /// Форматирует число элементов в понятную строку
- ///
- public class CountFormatter : IValueFormatter
- {
- #region Cвойства класса
- ///
- /// Имена чисел (тысяч, миллионов, миллиардов и т.п.)
- ///
- public string[] CountNames { get; set; } = { "", "тыс.", "млн.", "млрд." };
- ///
- /// Знаков после запятой
- ///
- public byte DecimalPlaces { get; set; } = 1;
- ///
- /// Делители чисел
- ///
- public long[] Delimeters { get; set; } = { 1000, 1000000, 1000000000 };
- #endregion
-
- #region Реализация интерфейса
- ///
- /// Реализация интерфейса
- ///
- public string[] ValueNames { get => CountNames; set => CountNames = value; }
- ///
- /// Реализация интерфейса
- ///
- public long[] MaxSizes { get => Delimeters; set => Delimeters = value; }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/anbs_cp/Enums/EOnExistAction.cs b/anbs_cp/Enums/EOnExistAction.cs
new file mode 100644
index 0000000..345050d
--- /dev/null
+++ b/anbs_cp/Enums/EOnExistAction.cs
@@ -0,0 +1,32 @@
+namespace anbs_cp.Enums;
+
+///
+/// Действия при операции переименования, если файл существует
+///
+public enum EOnExistAction
+{
+ ///
+ /// Возбуждать исключение
+ ///
+ RaiseException = 0,
+
+ ///
+ /// Прервать операцию
+ ///
+ Abort = 1,
+
+ ///
+ /// Продолжить операцию
+ ///
+ Ignore = 2,
+
+ ///
+ /// Возбуждать исключение, если папка не пуста (только для папок)
+ ///
+ RaiseExceptionIfNotEmpty = 3,
+
+ ///
+ /// Прервать операцию, если папка не пуста (только для папок)
+ ///
+ AbortIfNotEmpty = 4
+}
\ No newline at end of file
diff --git a/anbs_cp/FileSizeFormatter.cs b/anbs_cp/FileSizeFormatter.cs
deleted file mode 100644
index a4cbd33..0000000
--- a/anbs_cp/FileSizeFormatter.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-namespace anbs_cp
-{
- ///
- /// Форматирует размер файла/папки в понятную строку
- ///
- public class FileSizeFormatter : IValueFormatter
- {
- #region Cвойства класса
- ///
- /// Имена размеров (байт, килобайт, мегабайт, гигабайт и террабайт)
- ///
- public string[] SizeNames { get; set; } = { "Байт", "Кб", "Мб", "Гб", "Тб" };
- ///
- /// Знаков после запятой
- ///
- public byte DecimalPlaces { get; set; } = 2;
- ///
- /// Максимально байт (далее идут Кбайты)
- ///
- public long ByteMax { get; set; } = 1024;
- ///
- /// Максимально Кбайт (далее идут Мбайты)
- ///
- public long KByteMax { get; set; } = 1048576;
- ///
- /// Максимально Мбайт (далее идут Гбайты)
- ///
- public long MByteMax { get; set; } = 1073741824;
- ///
- /// Максимально Гбайт (далее идут Тбайты)
- ///
- public long GByteMax { get; set; } = 1099511627776;
- #endregion
-
- #region Реализация интерфейса
- ///
- /// Реализация интерфейса
- ///
- public string[] ValueNames { get => SizeNames; set => SizeNames = value; }
- ///
- /// Реализация интерфейса
- ///
- public long[] MaxSizes
- {
- get => new long[] { ByteMax, KByteMax, MByteMax, GByteMax };
- set
- {
- ByteMax = value[0];
- KByteMax = value[1];
- MByteMax = value[2];
- GByteMax = value[3];
- }
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/anbs_cp/IValueFormatter.cs b/anbs_cp/IValueFormatter.cs
deleted file mode 100644
index 36e0d3b..0000000
--- a/anbs_cp/IValueFormatter.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-namespace anbs_cp
-{
- ///
- /// Форматирует размерности в понятную строку
- ///
- public interface IValueFormatter
- {
-
- #region Определения интерфейса
- ///
- /// Имена размерностей
- ///
- public string[] ValueNames { get; set; }
- ///
- /// Знаков после запятой
- ///
- public byte DecimalPlaces { get; set; }
- ///
- /// Максимальные размеры (массив ulong[4])
- ///
- public long[] MaxSizes { get; set; }
- #endregion
-
- #region Методы интерфейса
- ///
- /// Форматирование размерности
- ///
- /// Размерность, требующая форматирования
- /// Форматированная размерность (например, 20 Мб)
- public string Format(long value)
- {
- //Левая граница
- long leftnum;
- //Правая граница
- long rightnum;
-
- for (int i = 0; i <= MaxSizes.Length; i++)
- {
- if (i == 0)
- leftnum = 0;
- else
- leftnum = MaxSizes[i - 1];
-
- if (i == MaxSizes.Length)
- rightnum = long.MaxValue;
- else
- rightnum = MaxSizes[i];
-
- if ((value >= leftnum) && (value < rightnum))
- return $"{FormatValue(value, leftnum)} {ValueNames[i]}";
-
- }
-
- return value.ToString();
- }
- ///
- /// Деление числа на число с DecimalPlaces знаками после запятой
- ///
- /// Делимое число
- /// Число-делитель
- /// Частное (с DecimalPlaces знаками после запятой)
- private string FormatValue(long dividend, long divider)
- {
- if (divider == 0)
- {
- return $"{dividend}";
- }
-
- long delim = 1;
-
- for (int i = 0; i <= DecimalPlaces; i++)
- {
- delim *= 10;
- }
-
- decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim;
-
- return $"{value}";
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IActionError.cs b/anbs_cp/Interfaces/IActionError.cs
new file mode 100644
index 0000000..38cf7bb
--- /dev/null
+++ b/anbs_cp/Interfaces/IActionError.cs
@@ -0,0 +1,14 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс ошибки
+///
+public interface IActionError : IActionStateMessage
+{
+ ///
+ /// Критичность ошибки:
+ /// при некритичных ошибках продолжение выполнения операции возможно,
+ /// а при критичных -- нет
+ ///
+ public bool IsCritical { get; init; }
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IActionInfo.cs b/anbs_cp/Interfaces/IActionInfo.cs
new file mode 100644
index 0000000..c48f47c
--- /dev/null
+++ b/anbs_cp/Interfaces/IActionInfo.cs
@@ -0,0 +1,12 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс для информации по статусу
+///
+public interface IActionInfo : IActionStateMessage
+{
+ ///
+ /// Статусная информация (например, начало работы)
+ ///
+ public bool IsStatusInfo { get; init; }
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IActionStateMessage.cs b/anbs_cp/Interfaces/IActionStateMessage.cs
new file mode 100644
index 0000000..e6af12b
--- /dev/null
+++ b/anbs_cp/Interfaces/IActionStateMessage.cs
@@ -0,0 +1,24 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс сообщения состояния
+///
+public interface IActionStateMessage
+{
+ ///
+ /// Объект сообщения
+ ///
+ public object Object { get; set; }
+
+ ///
+ /// Текст сообщения
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Функция вывода сообщения
+ ///
+ /// Строка-форматирование (например, «[{0}] - {1}»)
+ /// Отформатированную строка
+ public string PrintMessage (string format) => string.Format (format, Object, Message);
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IActionWarning.cs b/anbs_cp/Interfaces/IActionWarning.cs
new file mode 100644
index 0000000..23ec4cc
--- /dev/null
+++ b/anbs_cp/Interfaces/IActionWarning.cs
@@ -0,0 +1,12 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс предупреждения
+///
+public interface IActionWarning : IActionStateMessage
+{
+ ///
+ /// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию.
+ ///
+ public bool IsInformWarning { get; init; }
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IEncryptor.cs b/anbs_cp/Interfaces/IEncryptor.cs
new file mode 100644
index 0000000..4fb84ea
--- /dev/null
+++ b/anbs_cp/Interfaces/IEncryptor.cs
@@ -0,0 +1,37 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс шифрования
+///
+public interface IEncryptor
+{
+ ///
+ /// Метод для шифрования строки
+ ///
+ /// Строка, которая должна быть зашифрована
+ /// Ключ шифрования
+ /// Этот метод возвращает зашифрованную строку
+ string Encrypt (string value, string salt);
+
+ ///
+ /// Метод для дешифрования строки
+ ///
+ /// Строка, которая должна быть дешифрована
+ /// Ключ шифрования
+ /// Этот метод возвращает дешифрованную строку
+ string Decrypt (string encryptedValue, string salt);
+
+ ///
+ /// Декодирует зашифрованную строку в HTML-пригодный формат
+ ///
+ /// Зашифрованная строка
+ /// Этот метод возвращает дешифрованную строку
+ string Base64UrlEncode (string text);
+
+ ///
+ /// Раскодирует из декодированной строки в HTML-пригодный формат
+ ///
+ /// Декодированная строка
+ /// Этот метод возвращает шифрованную строку
+ string Base64UrlDecode (string text);
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IValueConverter.cs b/anbs_cp/Interfaces/IValueConverter.cs
new file mode 100644
index 0000000..2400136
--- /dev/null
+++ b/anbs_cp/Interfaces/IValueConverter.cs
@@ -0,0 +1,22 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Интерфейс конвертера величин для отображения (улучшенный аналог IValueFormatter)
+///
+public interface IValueConverter
+{
+ ///
+ /// Массив имён размерностей
+ ///
+ public string[] ValueNames { get; init; }
+
+ ///
+ /// Делитель
+ ///
+ public long Divider { get; init; }
+
+ ///
+ /// Знаков после запятой (0, 1, 2)
+ ///
+ public byte DecimalPlaces { get; init; }
+}
\ No newline at end of file
diff --git a/anbs_cp/Interfaces/IValueFormatter.cs b/anbs_cp/Interfaces/IValueFormatter.cs
new file mode 100644
index 0000000..2ae523d
--- /dev/null
+++ b/anbs_cp/Interfaces/IValueFormatter.cs
@@ -0,0 +1,74 @@
+namespace anbs_cp.Interfaces;
+
+///
+/// Форматирует размерности в понятную строку
+///
+public interface IValueFormatter
+{
+ #region Определения интерфейса
+
+ ///
+ /// Имена размерностей
+ ///
+ public string[] ValueNames { get; set; }
+
+ ///
+ /// Знаков после запятой
+ ///
+ public byte DecimalPlaces { get; set; }
+
+ ///
+ /// Максимальные размеры (массив ulong[4])
+ ///
+ public long[] MaxSizes { get; set; }
+
+ #endregion
+
+ #region Методы интерфейса
+
+ ///
+ /// Форматирование размерности
+ ///
+ /// Размерность, требующая форматирования
+ /// Форматированная размерность (например, 20 Мб)
+ public string Format(long value)
+ {
+ //Левая граница
+ long leftnum;
+ //Правая граница
+ long rightnum;
+
+ for (int i = 0; i <= MaxSizes.Length; i++)
+ {
+ leftnum = i == 0 ? 0 : MaxSizes[i - 1];
+
+ rightnum = i == MaxSizes.Length ? long.MaxValue : MaxSizes[i];
+
+ if (value >= leftnum && value < rightnum)
+ return $"{FormatValue(value, leftnum)} {ValueNames[i]}";
+ }
+
+ return value.ToString();
+ }
+
+ ///
+ /// Деление числа на число с DecimalPlaces знаками после запятой
+ ///
+ /// Делимое число
+ /// Число-делитель
+ /// Частное (с DecimalPlaces знаками после запятой)
+ private string FormatValue(long dividend, long divider)
+ {
+ if (divider == 0) return $"{dividend}";
+
+ long delim = 1;
+
+ for (int i = 0; i <= DecimalPlaces; i++) delim *= 10;
+
+ decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim;
+
+ return $"{value}";
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/LikeDelphi.cs b/anbs_cp/LikeDelphi.cs
deleted file mode 100644
index bf6831d..0000000
--- a/anbs_cp/LikeDelphi.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Collections.Generic;
-namespace anbs_cp
-{
- ///
- /// Класс, добавляющий реализацию некоторых методов Delphi, которые упрощают работу в C#.
- ///
- public static class LikeDelphi
- {
- ///
- /// Аналог функции IncludeTrailingBackslash
- ///
- /// Путь, к которому нужно добавить slash
- /// Путь со slash в конце
- public static string IncludeTrailingBackslash(string path)
- {
- string result = path;
- int Index = path.Length - 1;
- if (path[Index] != '\\')
- {
- result = $"{path}\\";
- }
- return result;
- }
- ///
- /// Парсер строки в множество строк
- ///
- /// Строка, которую нужно разбить
- /// Символ-делитель строки
- /// Массив строк
- public static List ParseString(string astring, char delim)
- {
- int from = -1;
- int to;
- List result = new();
- do
- {
- from++;
- to = astring.IndexOf(delim, from);
- if (to <= 0)
- to = astring.Length;
- if (from != to)
- result.Add(astring[from..(to-from)]);
- from = to;
- } while (to != astring.Length);
- return result;
- }
- }
-}
\ No newline at end of file
diff --git a/anbs_cp/Structs/KeyValue.cs b/anbs_cp/Structs/KeyValue.cs
new file mode 100644
index 0000000..ab42d49
--- /dev/null
+++ b/anbs_cp/Structs/KeyValue.cs
@@ -0,0 +1,51 @@
+namespace anbs_cp.Structs;
+
+///
+/// Пара ключ-значение
+///
+/// Тип ключа
+/// Тип значения
+public struct KeyValue
+{
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public KeyValue ()
+ {
+ Key = default;
+ Value = default;
+ }
+
+ ///
+ /// Конструктор со значениями
+ ///
+ /// Ключ
+ /// Значение
+ public KeyValue (TK key, TV value)
+ {
+ Key = key;
+ Value = value;
+ }
+ #endregion
+
+ #region Свойства
+ ///
+ /// Ключ
+ ///
+ public TK? Key { get; set; }
+
+ ///
+ /// Значение
+ ///
+ public TV? Value { get; set; }
+ #endregion
+
+ #region Методы
+ ///
+ /// Получает ключ-значение по умолчанию
+ ///
+ /// Ключ-значение по умолчанию
+ public static KeyValue GetDefault() => new();
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/Structs/TwoDimSize.cs b/anbs_cp/Structs/TwoDimSize.cs
new file mode 100644
index 0000000..1e8db7d
--- /dev/null
+++ b/anbs_cp/Structs/TwoDimSize.cs
@@ -0,0 +1,61 @@
+namespace anbs_cp.Structs;
+
+///
+/// Двумерный размер
+///
+public struct TwoDimSize
+{
+ #region Приватные поля
+ ///
+ /// Длина (приватное)
+ ///
+ private int _pWidth;
+
+ ///
+ /// Высота (приватное)
+ ///
+ private int _pHeight;
+ #endregion
+
+ #region Конструкторы
+ ///
+ /// Конструктор по умолчанию
+ ///
+ public TwoDimSize ()
+ {
+ Width = 0;
+ Height = 0;
+ }
+
+ ///
+ /// Конструктор
+ ///
+ /// Длина
+ /// Высота
+ public TwoDimSize (int width, int height)
+ {
+ Width = width;
+ Height = height;
+ }
+ #endregion
+
+ #region Свойства
+ ///
+ /// Длина
+ ///
+ public int Width
+ {
+ readonly get => _pWidth;
+ set => _pWidth = value < 0 ? 0 : value;
+ }
+
+ ///
+ /// Высота
+ ///
+ public int Height
+ {
+ readonly get => _pHeight;
+ set => _pHeight = value < 0 ? 0 : value;
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cp/TypeConverter.cs b/anbs_cp/TypeConverter.cs
deleted file mode 100644
index 3ab4951..0000000
--- a/anbs_cp/TypeConverter.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-namespace anbs_cp
-{
- ///
- /// Конвертер типов на манер Delphi
- ///
- public static class TypeConverter
- {
- #region Конвертация числа в строку
- ///
- /// Преобразование int в string
- ///
- /// Число
- /// Строка
- public static string IntToStr(int AInt) => AInt.ToString();
- ///
- /// Преобразование uint в string
- ///
- /// Число
- /// Строка
- public static string IntToStr(uint AInt) => AInt.ToString();
- ///
- /// Преобразование long в string
- ///
- /// Число
- /// Строка
- public static string IntToStr(long AInt) => AInt.ToString();
- ///
- /// Преобразование ulong в string
- ///
- /// Число
- /// Строка
- public static string IntToStr(ulong AInt) => AInt.ToString();
- ///
- /// Преобразование byte в string
- ///
- /// Число
- /// Строка
- public static string IntToStr(byte AInt) => AInt.ToString();
- #endregion
-
- #region Конвертация строки в число
- ///
- /// Преобразование строки в число
- ///
- /// Строка
- /// Значение по умолчанию (по умолчанию, 0)
- /// Число
- public static int StrToInt(string AStr, int ADefault = 0)
- {
- if (!int.TryParse(AStr, out int result))
- {
- result = ADefault;
- }
- return result;
- }
- ///
- /// Преобразование строки в число
- ///
- /// Строка
- /// Значение по умолчанию (по умолчанию, 0)
- /// Число
- public static uint StrToUInt(string AStr, uint ADefault = 0)
- {
- if (!uint.TryParse(AStr, out uint result))
- {
- result = ADefault;
- }
- return result;
- }
- ///
- /// Преобразование строки в число
- ///
- /// Строка
- /// Значение по умолчанию (по умолчанию, 0)
- /// Число
- public static long StrToInt64(string AStr, long ADefault = 0)
- {
- if (!long.TryParse(AStr, out long result))
- {
- result = ADefault;
- }
- return result;
- }
- ///
- /// Преобразование строки в число
- ///
- /// Строка
- /// Значение по умолчанию (по умолчанию, 0)
- /// Число
- public static ulong StrToUInt64(string AStr, ulong ADefault = 0)
- {
- if (!ulong.TryParse(AStr, out ulong result))
- {
- result = ADefault;
- }
- return result;
- }
- ///
- /// Преобразование строки в число
- ///
- /// Строка
- /// Значение по умолчанию (по умолчанию, 0)
- /// Число
- public static byte StrToByte(string AStr, byte ADefault = 0)
- {
- if (!byte.TryParse(AStr, out byte result))
- {
- result = ADefault;
- }
- return result;
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/anbs_cp/anbs_cp.csproj b/anbs_cp/anbs_cp.csproj
index 8d583a6..a6a5e8f 100644
--- a/anbs_cp/anbs_cp.csproj
+++ b/anbs_cp/anbs_cp.csproj
@@ -1,36 +1,51 @@
-
+
- net6.0
- 1.20211111.0
- Alexander Babaev
- ANB Software Components Pack
- Library of some useful functions in C# language.
- Alexander Babaev
+ net8.0
+ 2023.1114.0
+ Александр Бабаев
+ Набор компонентов ANB Software
+ Библиотека полезных методов языка C#
+ Александр Бабаев
anbs_cp
anbs_cp
enable
enable
True
- False
- https://github.com/GoodBoyAlex/anbsoftware_componentspack
- https://github.com/GoodBoyAlex/anbsoftware_componentspack
- 1.2021.1111
- 1.2021.1111
+ True
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+
+
+ ANBSoftware.ComponentsPack
+ MIT
+ 6.0
+ git
+ True
- 2
+ 7
True
+ none
- 2
+ 7
True
+ none
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
diff --git a/anbs_cp/anbs_cp.csproj.DotSettings b/anbs_cp/anbs_cp.csproj.DotSettings
new file mode 100644
index 0000000..632c268
--- /dev/null
+++ b/anbs_cp/anbs_cp.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp120
\ No newline at end of file
diff --git a/anbs_cpdb/Classes/MySqlEngine.cs b/anbs_cpdb/Classes/MySqlEngine.cs
new file mode 100644
index 0000000..e280601
--- /dev/null
+++ b/anbs_cpdb/Classes/MySqlEngine.cs
@@ -0,0 +1,369 @@
+using anbs_cp.Database.Interfaces;
+
+using Dapper;
+
+using MySqlConnector;
+
+namespace anbs_cp.Database.Classes;
+
+public class MySqlEngine: IDbEngine
+{
+ ///
+ /// Конструктор
+ ///
+ /// Строка подключения базы данных
+ public MySqlEngine (string connectionString) => ConnectionString = connectionString;
+
+ ///
+ /// Строка подключения базы данных
+ ///
+ public string ConnectionString { get; set; }
+
+ #region Базовые операции
+ ///
+ /// Выполняем команду
+ ///
+ /// Запрос
+ /// Данные запроса
+ /// Количество затронутых строк
+ public async Task ExecuteAsync (string sql, object? values = null)
+ {
+ // Подключаемся к БД
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Открываем соединение
+ await connection.OpenAsync();
+
+ // Выполняем команду и выводим результат
+ return await connection.ExecuteAsync(sql, values);
+ }
+
+ ///
+ /// Выполняем команду
+ ///
+ /// Запрос
+ /// Данные запроса
+ /// Количество затронутых строк
+ public int Execute (string sql, object? values = null) => ExecuteAsync(sql, values).GetAwaiter().GetResult();
+
+ ///
+ /// Запрос
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ public async Task> QueryAsync (string sql, object? values = null)
+ {
+ // Подключаемся к БД
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Открываем соединение
+ await connection.OpenAsync();
+
+ // Выполняем запрос и выводим результат
+ return await connection.QueryAsync(sql, values);
+ }
+
+ ///
+ /// Запрос
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ public IEnumerable Query (string sql, object? values = null) => QueryAsync(sql, values).GetAwaiter().GetResult();
+
+ ///
+ /// Запрос строки
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ public async Task QueryRowAsync (string sql, object? values = null)
+ {
+ // Подключаемся к БД
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Открываем соединение
+ await connection.OpenAsync();
+
+ // Выполняем запрос и выводим результат
+ return await connection.QuerySingleOrDefaultAsync(sql, values);
+ }
+
+ ///
+ /// Запрос строки
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ public T? QueryRow (string sql, object? values = null) => QueryRowAsync(sql, values).GetAwaiter().GetResult();
+
+ #endregion
+
+
+ #region Получение данных
+ ///
+ /// Получает массив данных (SELECT * FROM...)
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Массив результата запроса
+ public async Task> GetResultsAsync (string sql, object? values = null) => await QueryAsync(sql, values);
+
+ ///
+ /// Получает массив данных (SELECT * FROM...)
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Массив результата запроса
+ public IEnumerable GetResults (string sql, object? values = null) => GetResultsAsync(sql, values).GetAwaiter().GetResult();
+
+ ///
+ /// Получает строку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Строки данных или null
+ public async Task GetRowAsync (string sql, object? values = null)
+ {
+ // Подключаемся к БД
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Открываем соединение
+ await connection.OpenAsync();
+
+ // Выполняем запрос и выводим результат
+ return await connection.QuerySingleOrDefaultAsync(sql, values);
+ }
+
+ ///
+ /// Получает строку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Строки данных или null
+ public T? GetRow (string sql, object? values = null) => GetRowAsync(sql, values).GetAwaiter().GetResult();
+
+ ///
+ /// Получает колонку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Колонка данных или null
+ public async Task> GetColAsync (string sql, object? values = null)
+ where T : IComparable, IConvertible, IEquatable => await QueryAsync(sql, values);
+
+ ///
+ /// Получает колонку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Колонка данных или null
+ public IEnumerable GetCol (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable =>
+ GetColAsync(sql, values).GetAwaiter().GetResult();
+
+ ///
+ /// Получение значение единичного поля
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Поле или null
+ public async Task GetVarAsync (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable
+ {
+ // Подключаемся к БД
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Открываем соединение
+ await connection.OpenAsync();
+
+ // Выполняем запрос и выводим результат
+ return await connection.QuerySingleOrDefaultAsync(sql, values);
+ }
+
+ ///
+ /// Получение значение единичного поля
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Поле или null
+ public T? GetVar (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable =>
+ GetVarAsync(sql, values).GetAwaiter().GetResult();
+
+ #endregion
+
+ #region CRUD данные
+
+ ///
+ /// Вставляет данные в таблицу
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Результат выполнения
+ public async Task InsertAsync (T data, string tableName) where T : class
+ {
+ // Получение список имён свойств в data
+ List propertyNamesList = (from dataProperty in data.GetType().GetProperties() select dataProperty.Name).ToList();
+
+ // Получаем список имён в data, обрамленные @
+ List propertyValuesList = propertyNamesList.Select(static propertyName => $"@{propertyName}").ToList();
+
+ //Получаем строку имён свойств
+ string propertyNames = string.Join(", ", propertyNamesList.ToArray());
+
+ // Получаем строку имён свойств, обрамленных @
+ string propertyValues = string.Join(", ", propertyValuesList.ToArray());
+
+ // Создаю соединение
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Создаю запрос
+ string sql = $"""
+ INSERT
+ INTO {tableName} ({propertyNames})
+ VALUES ({propertyValues})
+ """;
+
+ // Выполняю запрос
+ return await connection.ExecuteAsync(sql, data) > 0;
+ }
+
+ ///
+ /// Вставляет данные в таблицу
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Результат выполнения
+ public bool Insert (T data, string tableName) where T : class => InsertAsync(data, tableName).GetAwaiter().GetResult();
+
+ ///
+ /// Обновляет строку в таблице
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public async Task UpdateAsync (T data, string tableName, string whereConditionColumn) where T : class
+ {
+ // Получение список имён свойств в data
+ List propertyNamesList = (from dataProperty in data.GetType().GetProperties()
+ where dataProperty.Name != whereConditionColumn
+ select dataProperty.Name).ToList();
+
+ // Получаем список имён в data, обрамленные @
+ List propertyKeyValuesList = propertyNamesList.Select(static propertyName => $"{propertyName}=@{propertyName}").ToList();
+
+ // Получаем строку имён свойств, обрамленных @
+ string properties = string.Join(", ", propertyKeyValuesList.ToArray());
+
+ // Создаю соединение
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Создаю запрос
+ string sql = $"""
+ UPDATE {tableName}
+ SET
+ {properties}
+ WHERE
+ {whereConditionColumn}=@{whereConditionColumn}
+ """;
+
+ // Выполняю запрос
+ return await connection.ExecuteAsync(sql, data) > 0;
+ }
+
+ ///
+ /// Обновляет строку в таблице
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public bool Update (T data, string tableName, string whereConditionColumn) where T : class =>
+ UpdateAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult();
+
+ ///
+ /// Удаляет строки
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public async Task DeleteAsync (T data, string tableName, string whereConditionColumn) where T : class
+ {
+ // Создаю соединение
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Создаю запрос
+ string sql = $"""
+ DELETE FROM
+ {tableName}
+ WHERE
+ {whereConditionColumn}=@{whereConditionColumn}
+ """;
+
+ // Выполняю запрос
+ return await connection.ExecuteAsync(sql, data) > 0;
+ }
+
+ ///
+ /// Удаляет строки
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public bool Delete (T data, string tableName, string whereConditionColumn) where T : class =>
+ DeleteAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult();
+
+ ///
+ /// Удаляет строку
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public async Task DeleteRowAsync (T data, string tableName, string whereConditionColumn) where T : class
+ {
+ // Создаю соединение
+ await using MySqlConnection connection = new(ConnectionString);
+
+ // Создаю запрос
+ string sql = $"""
+ DELETE FROM
+ {tableName}
+ WHERE
+ {whereConditionColumn}=@{whereConditionColumn}
+ LIMIT 1
+ """;
+
+ // Выполняю запрос
+ return await connection.ExecuteAsync(sql, data) > 0;
+ }
+
+ ///
+ /// Удаляет строку
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ public bool DeleteRow (T data, string tableName, string whereConditionColumn) where T : class =>
+ DeleteRowAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult();
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cpdb/Interfaces/IDbEngine.cs b/anbs_cpdb/Interfaces/IDbEngine.cs
new file mode 100644
index 0000000..b4f5943
--- /dev/null
+++ b/anbs_cpdb/Interfaces/IDbEngine.cs
@@ -0,0 +1,221 @@
+using System.Transactions;
+
+namespace anbs_cp.Database.Interfaces;
+
+///
+/// Интерфейс для работы с базой данных
+///
+public interface IDbEngine
+{
+ ///
+ /// Строка подключения
+ ///
+ string ConnectionString { get; set; }
+
+ #region Базовые операции
+
+ ///
+ /// Выполняем команду
+ ///
+ /// Запрос
+ /// Данные запроса
+ /// Количество затронутых строк
+ Task ExecuteAsync (string sql, object? values = null);
+
+ ///
+ /// Выполняем команду
+ ///
+ /// Запрос
+ /// Данные запроса
+ /// Количество затронутых строк
+ int Execute (string sql, object? values = null);
+
+ ///
+ /// Запрос
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ Task> QueryAsync (string sql, object? values = null);
+
+ ///
+ /// Запрос
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ IEnumerable Query (string sql, object? values = null);
+
+ ///
+ /// Запрос строки
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ Task QueryRowAsync (string sql, object? values = null);
+
+ ///
+ /// Запрос строки
+ ///
+ /// Тип передаваемого значения
+ /// Запрос
+ /// Данные запроса
+ /// Возвращает массив типа или значение по умолчанию
+ T? QueryRow (string sql, object? values = null);
+ #endregion
+
+ #region Получение данных
+
+ ///
+ /// Получает массив данных (SELECT * FROM...)
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Массив результата запроса
+ Task> GetResultsAsync (string sql, object? values = null);
+
+ ///
+ /// Получает массив данных (SELECT * FROM...)
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Массив результата запроса
+ IEnumerable GetResults (string sql, object? values = null);
+
+ ///
+ /// Получает строку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Строки данных или null
+ Task GetRowAsync (string sql, object? values = null);
+
+ ///
+ /// Получает строку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Строки данных или null
+ T? GetRow (string sql, object? values = null);
+
+ ///
+ /// Получает колонку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Колонка данных или null
+ Task> GetColAsync (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable;
+
+ ///
+ /// Получает колонку в массиве данных
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Колонка данных или null
+ IEnumerable GetCol (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable;
+
+ ///
+ /// Получение значение единичного поля
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Поле или null
+ Task GetVarAsync (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable;
+
+ ///
+ /// Получение значение единичного поля
+ ///
+ /// Тип получаемых данных
+ /// SQL-запрос
+ /// Данные запроса
+ /// Поле или null
+ T? GetVar (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable;
+
+ #endregion
+
+ #region CRUD данные
+ ///
+ /// Вставляет данные в таблицу
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Результат выполнения
+ Task InsertAsync (T data, string tableName) where T: class;
+
+ ///
+ /// Вставляет данные в таблицу
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Результат выполнения
+ bool Insert (T data, string tableName) where T: class;
+
+ ///
+ /// Обновляет строку в таблице
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ Task UpdateAsync (T data, string tableName, string whereConditionColumn) where T: class;
+
+ ///
+ /// Обновляет строку в таблице
+ ///
+ /// Класс данных
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ bool Update (T data, string tableName, string whereConditionColumn) where T: class;
+
+ ///
+ /// Удаляет строки
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ Task DeleteAsync (T data, string tableName, string whereConditionColumn) where T: class;
+
+ ///
+ /// Удаляет строки
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ bool Delete (T data, string tableName, string whereConditionColumn) where T: class;
+
+ ///
+ /// Удаляет строку
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ Task DeleteRowAsync (T data, string tableName, string whereConditionColumn) where T: class;
+
+ ///
+ /// Удаляет строку
+ ///
+ /// Данные
+ /// Имя таблицы
+ /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data
+ /// Результат выполнения
+ bool DeleteRow (T data, string tableName, string whereConditionColumn) where T: class;
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cpdb/anbs_cpdb.csproj b/anbs_cpdb/anbs_cpdb.csproj
new file mode 100644
index 0000000..0624317
--- /dev/null
+++ b/anbs_cpdb/anbs_cpdb.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net8.0
+ enable
+ enable
+ anbs_cp_db
+ anbs_cp.Database
+ True
+ ANBSoftware.ComponentsPack.Database
+ 2023.11.14.0
+ Александр Бабаев
+ Набор компонентов ANB Software для работы с БД
+ Библиотека полезных методов языка C# для работы с базами данных
+ Александр Бабаев
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ git
+
+
+
+
+
+
+
+
diff --git a/anbs_cpdb/anbs_cpdb.csproj.DotSettings b/anbs_cpdb/anbs_cpdb.csproj.DotSettings
new file mode 100644
index 0000000..632c268
--- /dev/null
+++ b/anbs_cpdb/anbs_cpdb.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp120
\ No newline at end of file
diff --git a/anbs_cpfn/Classes/NetFileExtension.cs b/anbs_cpfn/Classes/NetFileExtension.cs
new file mode 100644
index 0000000..bef0227
--- /dev/null
+++ b/anbs_cpfn/Classes/NetFileExtension.cs
@@ -0,0 +1,17 @@
+using Microsoft.AspNetCore.Http;
+
+namespace anbs_cp.ForNet.Classes;
+
+///
+/// Класс -- расширение для класса File
+///
+public class NetFileExtension
+{
+ ///
+ /// Получает MIME-тип файла
+ ///
+ /// Загружаемый файл
+ /// MIME-тип файла
+ public static string MIMEType (IFormFile file) =>
+ file.ContentType;
+}
\ No newline at end of file
diff --git a/anbs_cpfn/Classes/NetFileHash.cs b/anbs_cpfn/Classes/NetFileHash.cs
new file mode 100644
index 0000000..fc2e50c
--- /dev/null
+++ b/anbs_cpfn/Classes/NetFileHash.cs
@@ -0,0 +1,38 @@
+using System.Security.Cryptography;
+
+using anbs_cp.Classes;
+
+using Microsoft.AspNetCore.Http;
+
+namespace anbs_cp.ForNet.Classes;
+
+public static class NetFileHash
+{
+ ///
+ /// Получение md5-хэша загружаемого файла.
+ /// Взято с https://stackoverflow.com/a/67081012/16469671
+ ///
+ /// Загружаемый файл
+ /// Массив хэша
+ public static FileHash GetFileHash (IFormFile file)
+ {
+ //Создаю md5
+ using MD5 md5 = MD5.Create();
+
+ //Создаю поток для чтения
+ using StreamReader streamReader = new(file.OpenReadStream());
+
+ //Получаю строковый хэш
+ string hash = BitConverter.ToString(md5.ComputeHash(streamReader.BaseStream)).Replace("-", "")
+ .ToLowerInvariant();
+
+ //Создаю результат
+ FileHash fileHash = new();
+
+ //Вношу в него данные
+ fileHash.FromString(hash);
+
+ //Возвращаю результат
+ return fileHash;
+ }
+}
\ No newline at end of file
diff --git a/anbs_cpfn/Classes/NetTypeConverter.cs b/anbs_cpfn/Classes/NetTypeConverter.cs
new file mode 100644
index 0000000..5aceca8
--- /dev/null
+++ b/anbs_cpfn/Classes/NetTypeConverter.cs
@@ -0,0 +1,35 @@
+using System.Text.Encodings.Web;
+
+using Microsoft.AspNetCore.Html;
+
+namespace anbs_cp.ForNet.Classes;
+
+///
+/// Расширение конвертера типов на манер Delphi
+///
+public static class NetTypeConverter
+{
+ #region Конвернтация IHtmlContent
+ ///
+ /// Преобразует тип в строку .
+ ///
+ /// Значение, которое нужно преобразовать.
+ ///
+ public static string HtmlContentToString(IHtmlContent content)
+ {
+ //Создаём writer
+ using StringWriter writer = new();
+ //Конвертируем IHtmlContent в string
+ content.WriteTo(writer, HtmlEncoder.Default);
+ //Возвращаем результат
+ return writer.ToString();
+ }
+
+ ///
+ /// Преобразует строку в тип .
+ ///
+ /// Значение, которое нужно преобразовать.
+ ///
+ public static IHtmlContent StringToHtmlContent(string content) => new HtmlContentBuilder().AppendHtml(content);
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cpfn/Classes/PasswordEncrypt.cs b/anbs_cpfn/Classes/PasswordEncrypt.cs
new file mode 100644
index 0000000..a338eb2
--- /dev/null
+++ b/anbs_cpfn/Classes/PasswordEncrypt.cs
@@ -0,0 +1,56 @@
+using System.Text;
+
+using anbs_cp.Interfaces;
+
+using Microsoft.AspNetCore.Cryptography.KeyDerivation;
+
+namespace anbs_cp.ForNet.Classes;
+
+///
+/// Класс шифрования пароля
+///
+public sealed class PasswordEncrypt: IEncryptor
+{
+ ///
+ /// Шифрование пароля
+ ///
+ /// Пароль
+ /// Хэш-код пароля
+ /// Зашифрованный пароль
+ public string Encrypt (string password, string salt)
+ {
+ // Получаю byte-массив из хэш-кода пароля
+ byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
+
+ // Шифрую пароль
+ byte[] encryptedPassword = KeyDerivation.Pbkdf2(password, saltBytes, KeyDerivationPrf.HMACSHA512, 5000, 64);
+
+ // Возвращаю зашифрованный пароль
+ return Convert.ToBase64String(encryptedPassword);
+ }
+
+ ///
+ /// Этот метод не требует реализации в этом классе!
+ ///
+ /// НЕ РАБОТАЕТ
+ /// НЕ РАБОТАЕТ
+ /// НЕ РАБОТАЕТ
+ /// Этот метод не требует реализации в этом классе!
+ public string Decrypt (string encryptedValue, string salt) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
+
+ ///
+ /// Этот метод не требует реализации в этом классе!
+ ///
+ /// НЕ РАБОТАЕТ
+ /// НЕ РАБОТАЕТ
+ /// Этот метод не требует реализации в этом классе!
+ public string Base64UrlEncode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
+
+ ///
+ /// Этот метод не требует реализации в этом классе!
+ ///
+ /// НЕ РАБОТАЕТ
+ /// НЕ РАБОТАЕТ
+ /// Этот метод не требует реализации в этом классе!
+ public string Base64UrlDecode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
+}
\ No newline at end of file
diff --git a/anbs_cpfn/Extensions/UrlHelperExtension.cs b/anbs_cpfn/Extensions/UrlHelperExtension.cs
new file mode 100644
index 0000000..a793f56
--- /dev/null
+++ b/anbs_cpfn/Extensions/UrlHelperExtension.cs
@@ -0,0 +1,110 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.WebUtilities;
+using Microsoft.Extensions.Primitives;
+
+namespace anbs_cp.ForNet.Extensions;
+
+///
+/// Расширение URLHelper
+///
+public static class UrlHelperExtension
+{
+ ///
+ /// Очищает URL, удаляя ненужные QueryString
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Ссылка, которую нужно почистить
+ /// Массив ключей, которые нужно удалить
+ /// Возвращать только локальную ссылку
+ ///
+ public static string ParseURLQuery(this IUrlHelper helper, HttpContext context, string? url,
+ string[] clearQueryString, bool getLocalURL = true)
+ {
+ //Получаю returnURL
+ url ??= "/";
+
+ //Если адрес локальный, то преобразую в полный
+ if (helper.IsLocalUrl(url))
+ url = LocalToFullURL(helper, context, url);
+
+ //Создаю uri по адресу
+ Uri uri = new(url ?? "");
+
+ //Формат
+ const UriFormat format = UriFormat.UriEscaped;
+
+ //Формирую Uri-адрес сайта
+ string baseUri =
+ uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port,
+ format);
+
+ //Формирую локальную ссылку
+ string localUri = uri.GetComponents(UriComponents.Path, format);
+
+ //Создаю словарь запроса
+ Dictionary query = QueryHelpers.ParseQuery(uri.Query);
+
+ //Если он содержит параметр для очистки, то удаляю его
+ foreach (KeyValuePair queryItem in query.Where(queryItem =>
+ clearQueryString.Contains(queryItem.Key)))
+ query.Remove(queryItem.Key);
+
+ //Создаю список запроса, пригодный для QueryBuilder
+ List> queryList = query.Select(static queryItem =>
+ new KeyValuePair(queryItem.Key, queryItem.Value.ToString())).ToList();
+
+ //Запускаю построение новых параметров
+ QueryBuilder qBuilder = new(queryList);
+
+ //Создаю переменную-результат
+ string result = "";
+
+ //Если нужно получить полную ссылку
+ if (!getLocalURL)
+ result = baseUri;
+
+ //формирую переменную-результат
+ result = $"{result}/{localUri}{qBuilder.ToQueryString()}";
+
+ //Вывожу результат
+ return result;
+ }
+
+ ///
+ /// Получает локальный url-адрес
+ ///
+ ///
+ /// url-адрес
+ /// Локальный url-адрес
+ public static string ToLocalURL (this IUrlHelper helper, string url)
+ {
+ //Создаю uri из url
+ Uri uri = new(url);
+
+ //Вывожу результат
+ return helper.IsLocalUrl(url) ? url : uri.PathAndQuery;
+ }
+
+ ///
+ /// Преобразует локальную ссылку в полную
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Ссылка
+ ///
+ ///
+ ///
+ public static string? LocalToFullURL (this IUrlHelper helper, HttpContext context, string? url) =>
+ helper.IsLocalUrl(url) ? $"{context.Request.Scheme}://{context.Request.Host}{url}" : url;
+}
\ No newline at end of file
diff --git a/anbs_cpfn/anbs_cpfn.csproj b/anbs_cpfn/anbs_cpfn.csproj
new file mode 100644
index 0000000..dda3682
--- /dev/null
+++ b/anbs_cpfn/anbs_cpfn.csproj
@@ -0,0 +1,38 @@
+
+
+
+ net8.0
+ enable
+ enable
+ True
+ ANBSoftware.ComponentsPackForNet
+ 2023.11.14.0
+ Александр Бабаев
+ Набор компонентов ANB Software для ASP.NET Core
+ Библиотека полезных методов языка C# для ASP.NET Core
+ Александр Бабаев
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ git
+ MIT
+ anbs_cp.ForNet
+ anbs_cp_fn
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/anbs_cpfn/anbs_cpfn.csproj.DotSettings b/anbs_cpfn/anbs_cpfn.csproj.DotSettings
new file mode 100644
index 0000000..632c268
--- /dev/null
+++ b/anbs_cpfn/anbs_cpfn.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp120
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsDriveInfo.cs b/anbs_cposinfo/Classes/OsDriveInfo.cs
new file mode 100644
index 0000000..8ec8ce0
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsDriveInfo.cs
@@ -0,0 +1,59 @@
+using anbs_cp.OsInfo.Enums;
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Информация о дисках
+///
+public sealed class OsDriveInfo: IOsDriveInfo
+{
+ ///
+ /// Конструктор
+ ///
+ public OsDriveInfo ()
+ {
+ Type = EDriveType.DtHardDisc;
+ Caption = null;
+ Description = null;
+ DeviceId = null;
+ Name = null;
+ Model = null;
+ TotalSize = 0;
+ }
+
+ ///
+ /// Тип диска
+ ///
+ public EDriveType Type { get; set; }
+
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get; set; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Идентификатор устройства
+ ///
+ public string? DeviceId { get; set; }
+
+ ///
+ /// Имя устройства
+ ///
+ public string? Name { get; set; }
+
+ ///
+ /// Модель
+ ///
+ public string? Model { get; set; }
+
+ ///
+ /// Общий размер
+ ///
+ public ulong TotalSize { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsInfo.cs b/anbs_cposinfo/Classes/OsInfo.cs
new file mode 100644
index 0000000..7b6da2d
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsInfo.cs
@@ -0,0 +1,402 @@
+using System.Management;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+
+using anbs_cp.Classes;
+using anbs_cp.OsInfo.Enums;
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Информация о системе
+///
+public static class OsInfo
+{
+ ///
+ /// Конструктор
+ ///
+ static OsInfo ()
+ {
+ Windows = GetWindowsInfo();
+ Processors = GetProcessors();
+ RAM = GetRAMs();
+ Videos = GetVideoAdapterInfos();
+ Drives = GetDriveInfos();
+ Net = GetNet();
+ }
+
+ ///
+ /// Информация о Windows
+ ///
+ public static IOsWindowsInfo Windows { get; }
+
+ ///
+ /// Список с информацией о процессоре(-ах)
+ ///
+ public static List Processors { get; }
+
+ ///
+ /// Количество оперативной памяти в байтах
+ ///
+ public static ulong RAM { get; }
+
+ ///
+ /// Видеоадаптеры
+ ///
+ public static List Videos { get; }
+
+ ///
+ /// Диски
+ ///
+ public static List Drives { get; set; }
+
+ ///
+ /// Сеть
+ ///
+ public static List Net { get; set; }
+
+ #region Служебные методы
+ ///
+ /// Получает информацию о Windows
+ ///
+ ///
+ private static IOsWindowsInfo GetWindowsInfo () =>
+ new OsWindowsInfo
+ {
+ Version = Environment.OSVersion.ToString(),
+ Is64 = Environment.Is64BitOperatingSystem,
+ PcName = Environment.MachineName,
+ WindowsFolder = Environment.SystemDirectory
+ };
+
+ ///
+ /// Получение процессоров
+ ///
+ /// Список информации о процессорах
+ private static List GetProcessors ()
+ {
+ try
+ {
+ //Создаю результирующий список
+ List processorsList = new();
+
+ //Создаю классы менеджмента
+ ManagementClass management = new("Win32_Processor");
+ ManagementObjectCollection collection = management.GetInstances();
+
+ //Получаю число процессоров
+ int processorsCount = collection.Cast()
+ .Select(static a => a.Properties["ProcessorId"].Value.ToString()).Count();
+
+ //Перебираю массив данных
+ for (int ind = 0; ind < processorsCount; ind++)
+ {
+ //Создаю элемент информации о процессоре
+ OsProcessorInfo processor = new()
+ {
+ Caption = collection.Cast()
+ .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind),
+ Description = collection.Cast()
+ .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind),
+ DeviceId = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind),
+ Manufacturer = collection.Cast()
+ .Select(static a => a.Properties["Manufacturer"].Value.ToString()).ElementAtOrDefault(ind),
+ MaxClockSpeed = TypeConverter.StrToInt(collection.Cast()
+ .Select(static a =>
+ a.Properties["MaxClockSpeed"].Value.ToString())
+ .ElementAtOrDefault(ind) ??
+ "0"),
+ Name = collection.Cast()
+ .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind),
+ NumberOfCores = TypeConverter.StrToInt(collection.Cast()
+ .Select(static a =>
+ a.Properties["NumberOfCores"].Value.ToString())
+ .ElementAtOrDefault(ind) ??
+ "0"),
+ NumberOfLogicalProcessors = TypeConverter.StrToInt(collection.Cast()
+ .Select(static a => a.Properties["NumberOfLogicalProcessors"].Value.ToString())
+ .ElementAtOrDefault(ind) ?? "0")
+ };
+
+ //Добавляю в список
+ processorsList.Add(processor);
+ }
+
+ //Возвращаю список
+ return processorsList;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+
+ ///
+ /// Получение общее количество оперативной памяти
+ ///
+ /// Список информации о количестве оперативной памяти
+ private static ulong GetRAMs ()
+ {
+ try
+ {
+ //Создаю классы менеджмента
+ ManagementClass management = new("Win32_ComputerSystem");
+ ManagementObjectCollection collection = management.GetInstances();
+
+ //Получаю результат
+ return TypeConverter.StrToUInt64(collection.Cast()
+ .Select(static a => a.Properties["TotalPhysicalMemory"].Value.ToString()).FirstOrDefault() ?? "0");
+ }
+ catch (NullReferenceException)
+ {
+ return 0;
+ }
+ }
+
+ ///
+ /// Получает список видеоадаптеров
+ ///
+ /// Список информации о видеоадаптерах
+ private static List GetVideoAdapterInfos ()
+ {
+ try
+ {
+ //Создаю результирующий список
+ List videosList = new();
+
+ //Создаю классы менеджмента
+ ManagementClass management = new("Win32_VideoController");
+ ManagementObjectCollection collection = management.GetInstances();
+
+ //Получаю число адаптеров
+ int count = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count();
+
+ //Перебираю массив данных
+ for (int ind = 0; ind < count; ind++)
+ {
+ //Создаю элемент информации об адаптере
+ OsVideoAdapterInfo adapter = new()
+ {
+ Caption = collection.Cast()
+ .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind),
+ Description = collection.Cast()
+ .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind),
+ DeviceId = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind),
+ AdapterRAM = TypeConverter.StrToInt(collection.Cast()
+ .Select(static a => a.Properties["AdapterRAM"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"),
+ DriverDate = collection.Cast()
+ .Select(static a => a.Properties["DriverDate"].Value.ToString()).ElementAtOrDefault(ind),
+ Name = collection.Cast()
+ .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind),
+ CurrentResolution = (TypeConverter.StrToInt(collection.Cast()
+ .Select(static a => a.Properties["CurrentHorizontalResolution"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"),
+ TypeConverter.StrToInt(collection.Cast()
+ .Select(static a => a.Properties["CurrentVerticalResolution"].Value.ToString())
+ .ElementAtOrDefault(ind) ?? "0")),
+ SystemName = collection.Cast()
+ .Select(static a => a.Properties["SystemName"].Value.ToString()).ElementAtOrDefault(ind),
+ DriverVersion = collection.Cast()
+ .Select(static a => a.Properties["DriverVersion"].Value.ToString()).ElementAtOrDefault(ind),
+ InstalledDisplayDrivers = collection.Cast()
+ .Select(static a => a.Properties["InstalledDisplayDrivers"].Value.ToString()).ElementAtOrDefault(ind),
+ VideoProcessor = collection.Cast()
+ .Select(static a => a.Properties["VideoProcessor"].Value.ToString()).ElementAtOrDefault(ind)
+ };
+
+ //Добавляю в список
+ videosList.Add(adapter);
+ }
+
+ //Возвращаю список
+ return videosList;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+
+ ///
+ /// Получает список дисков
+ ///
+ /// Список информации о дисках
+ private static List GetDriveInfos ()
+ {
+ try
+ {
+ //Создаю результат
+ List result = new();
+
+ //Добавление всех HDD/SSD дисков
+ result.AddRange(GetHDDs());
+
+ //Добавление всех CD/DVD/BD дисков
+ result.AddRange(GetCDRom());
+
+ //Вывожу список
+ return result;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+
+ ///
+ /// Получаю список HDD/SSD дисков
+ ///
+ /// Информация обо всех HDD/SSD дисках
+ private static List GetHDDs ()
+ {
+ try
+ {
+ //Создаю результирующий список
+ List driveList = new();
+
+ //Создаю классы менеджмента
+ ManagementClass management = new("Win32_DiskDrive");
+ ManagementObjectCollection collection = management.GetInstances();
+
+ //Получаю число адаптеров
+ int count = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count();
+
+ //Перебираю массив данных
+ for (int ind = 0; ind < count; ind++)
+ {
+ //Создаю элемент информации об адаптере
+ OsDriveInfo drive = new()
+ {
+ Type = EDriveType.DtHardDisc,
+ Caption = collection.Cast()
+ .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind),
+ Description = collection.Cast()
+ .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind),
+ DeviceId = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind),
+ Name = collection.Cast()
+ .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind),
+ TotalSize = TypeConverter.StrToUInt64(collection.Cast()
+ .Select(static a => a.Properties["Size"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"),
+ Model = collection.Cast()
+ .Select(static a => a.Properties["Model"].Value.ToString()).ElementAtOrDefault(ind)
+ };
+
+ //Добавляю в список
+ driveList.Add(drive);
+ }
+
+ //Возвращаю список
+ return driveList;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+
+ ///
+ /// Получаю список CD/DVD/BD дисков
+ ///
+ /// Информация обо всех CD/DVD/BD дисках
+ private static List GetCDRom ()
+ {
+ try
+ {
+ //Создаю результирующий список
+ List driveList = new();
+
+ //Создаю классы менеджмента
+ ManagementClass management = new("Win32_CDROMDrive");
+ ManagementObjectCollection collection = management.GetInstances();
+
+ //Получаю число адаптеров
+ int count = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count();
+
+ //Перебираю массив данных
+ for (int ind = 0; ind < count; ind++)
+ {
+ //Создаю элемент информации об адаптере
+ OsDriveInfo drive = new()
+ {
+ Type = EDriveType.DtCDRom,
+ Caption = collection.Cast()
+ .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind),
+ Description = collection.Cast()
+ .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind),
+ DeviceId = collection.Cast()
+ .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind),
+ Name = collection.Cast()
+ .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind),
+ //Ставится 0, чтобы не проверять корректность загрузки и читаемость диска, а также избежать удлинения получения информации
+ TotalSize = 0,
+ Model = collection.Cast()
+ .Select(static a => a.Properties["Manufacturer"].Value.ToString()).ElementAtOrDefault(ind)
+ };
+
+ //Добавляю в список
+ driveList.Add(drive);
+ }
+
+ //Возвращаю список
+ return driveList;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+
+ ///
+ /// Получаю информацию о сети интернет
+ ///
+ /// Информация о сети интернет
+ private static List GetNet ()
+ {
+ try
+ {
+ //Создаю результирующий список
+ List netList = new();
+
+ //Получаю информацию о всех сетевых интерфейсах
+ foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
+ {
+ //Создаю элемент
+ OsNetInfo netInfo = new()
+ {
+ Name = adapter.Name,
+ Description = adapter.Description,
+ MacAddress = adapter.OperationalStatus == OperationalStatus.Up
+ ? adapter.GetPhysicalAddress().ToString()
+ : null
+ };
+
+ //Получаю IP-адрес
+ foreach (UnicastIPAddressInformation info in adapter.GetIPProperties().UnicastAddresses.Where(
+ static info =>
+ info.Address.AddressFamily == AddressFamily.InterNetwork && info.IsDnsEligible))
+ {
+ if (!string.IsNullOrWhiteSpace(netInfo.IPAddress))
+ netInfo.IPAddress += ";";
+ netInfo.IPAddress += info.Address.ToString();
+ }
+
+ //Добавляю адаптер
+ netList.Add(netInfo);
+ }
+
+ //Возвращаю список
+ return netList;
+ }
+ catch (NullReferenceException)
+ {
+ return new();
+ }
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsNetInfo.cs b/anbs_cposinfo/Classes/OsNetInfo.cs
new file mode 100644
index 0000000..e5b416b
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsNetInfo.cs
@@ -0,0 +1,39 @@
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Информация об интернет-соединении
+///
+public sealed class OsNetInfo: IOsNetInfo
+{
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get => Name; set => _ = value; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Идентификатор устройства
+ ///
+ public string? DeviceId { get => Name; set => _ = value; }
+
+ ///
+ /// Имя устройства
+ ///
+ public string? Name { get; set; }
+
+ ///
+ /// IP-адрес
+ ///
+ public string? IPAddress { get; set; }
+
+ ///
+ /// MAC-адрес
+ ///
+ public string? MacAddress { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsProcessorInfo.cs b/anbs_cposinfo/Classes/OsProcessorInfo.cs
new file mode 100644
index 0000000..df3bba8
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsProcessorInfo.cs
@@ -0,0 +1,64 @@
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Класс информации о процессоре
+///
+public sealed class OsProcessorInfo: IOsProcessorInfo
+{
+ ///
+ /// Конструктор
+ ///
+ public OsProcessorInfo ()
+ {
+ Caption = null;
+ Description = null;
+ DeviceId = null;
+ Manufacturer = null;
+ MaxClockSpeed = 0;
+ Name = null;
+ NumberOfCores = 0;
+ NumberOfLogicalProcessors = 0;
+ }
+
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get; set; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Идентификатор процессора в системе
+ ///
+ public string? DeviceId { get; set; }
+
+ ///
+ /// Производитель
+ ///
+ public string? Manufacturer { get; set; }
+
+ ///
+ /// Максимальная тактовая частота
+ ///
+ public int MaxClockSpeed { get; set; }
+
+ ///
+ /// Имя процессора
+ ///
+ public string? Name { get; set; }
+
+ ///
+ /// Число ядер
+ ///
+ public int NumberOfCores { get; set; }
+
+ ///
+ /// Число потоков
+ ///
+ public int NumberOfLogicalProcessors { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs b/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs
new file mode 100644
index 0000000..2b46a7a
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs
@@ -0,0 +1,82 @@
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Информация о видеокарте
+///
+internal sealed class OsVideoAdapterInfo: IOsVideoAdapterInfo
+{
+ ///
+ /// Конструктор
+ ///
+ public OsVideoAdapterInfo ()
+ {
+ AdapterRAM = 0;
+ Caption = null;
+ CurrentResolution = (0, 0);
+ Description = null;
+ DeviceId = null;
+ DriverDate = null;
+ DriverVersion = null;
+ InstalledDisplayDrivers = null;
+ Name = null;
+ SystemName = null;
+ VideoProcessor = null;
+ }
+
+ ///
+ /// Память
+ ///
+ public int AdapterRAM { get; set; }
+
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get; set; }
+
+ ///
+ /// Текущее разрешение
+ ///
+ public (int, int) CurrentResolution { get; set; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Идентификатор устройства
+ ///
+ public string? DeviceId { get; set; }
+
+ ///
+ /// Дата установки драйвера
+ ///
+ public string? DriverDate { get; set; }
+
+ ///
+ /// Версия драйвера
+ ///
+ public string? DriverVersion { get; set; }
+
+ ///
+ /// Название драйверов
+ ///
+ public string? InstalledDisplayDrivers { get; set; }
+
+ ///
+ /// Имя
+ ///
+ public string? Name { get; set; }
+
+ ///
+ /// Имя в системе
+ ///
+ public string? SystemName { get; set; }
+
+ ///
+ /// Видео процессор
+ ///
+ public string? VideoProcessor { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Classes/OsWindowsInfo.cs b/anbs_cposinfo/Classes/OsWindowsInfo.cs
new file mode 100644
index 0000000..3218361
--- /dev/null
+++ b/anbs_cposinfo/Classes/OsWindowsInfo.cs
@@ -0,0 +1,62 @@
+using anbs_cp.OsInfo.Interfaces;
+
+namespace anbs_cp.OsInfo.Classes;
+
+///
+/// Информация о Windows
+///
+public sealed class OsWindowsInfo: IOsWindowsInfo
+{
+ ///
+ /// Конструктор
+ ///
+ public OsWindowsInfo ()
+ {
+ Version = null;
+ Is64 = true;
+ PcName = null;
+ WindowsFolder = null;
+ }
+
+ ///
+ /// Версия
+ ///
+ public string? Version { get; set; }
+
+ ///
+ /// 64-разрядная ОС
+ ///
+ public bool Is64 { get; set; }
+
+ ///
+ /// Имя компьютера
+ ///
+ public string? PcName { get; set; }
+
+ ///
+ /// Путь к папке Windows
+ ///
+ public string? WindowsFolder { get; set; }
+
+ #region Реализация интерфейса IBasicInfo
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get => Version; set => _ = value; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get => Version; set => _ = value; }
+
+ ///
+ /// Идентификатор
+ ///
+ public string? DeviceId { get => Version; set => _ = value; }
+
+ ///
+ /// Имя
+ ///
+ public string? Name { get => Version; set => _ = value; }
+ #endregion
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Enums/EDriveType.cs b/anbs_cposinfo/Enums/EDriveType.cs
new file mode 100644
index 0000000..c8af779
--- /dev/null
+++ b/anbs_cposinfo/Enums/EDriveType.cs
@@ -0,0 +1,17 @@
+namespace anbs_cp.OsInfo.Enums;
+
+///
+/// Тип носителя
+///
+public enum EDriveType
+{
+ ///
+ /// HDD/SSD/M2
+ ///
+ DtHardDisc = 0,
+
+ ///
+ /// Диск CD/DVD/BD
+ ///
+ DtCDRom = 1
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsBasicInfo.cs b/anbs_cposinfo/Interfaces/IOsBasicInfo.cs
new file mode 100644
index 0000000..2d40df6
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsBasicInfo.cs
@@ -0,0 +1,27 @@
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Базовые параметры устройства
+///
+public interface IOsBasicInfo
+{
+ ///
+ /// Заголовок
+ ///
+ public string? Caption { get; set; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Идентификатор устройства
+ ///
+ public string? DeviceId { get; set; }
+
+ ///
+ /// Имя устройства
+ ///
+ public string? Name { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsDriveInfo.cs b/anbs_cposinfo/Interfaces/IOsDriveInfo.cs
new file mode 100644
index 0000000..04cfdd1
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsDriveInfo.cs
@@ -0,0 +1,24 @@
+using anbs_cp.OsInfo.Enums;
+
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Информация о дисках
+///
+public interface IOsDriveInfo: IOsBasicInfo
+{
+ ///
+ /// Тип диска
+ ///
+ public EDriveType Type { get; set; }
+
+ ///
+ /// Модель
+ ///
+ public string? Model { get; set; }
+
+ ///
+ /// Общий размер
+ ///
+ public ulong TotalSize { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsNetInfo.cs b/anbs_cposinfo/Interfaces/IOsNetInfo.cs
new file mode 100644
index 0000000..5e54e62
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsNetInfo.cs
@@ -0,0 +1,17 @@
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Информация об интернет-соединении
+///
+public interface IOsNetInfo: IOsBasicInfo
+{
+ ///
+ /// IP-адрес
+ ///
+ public string? IPAddress { get; set; }
+
+ ///
+ /// MAC-адрес
+ ///
+ public string? MacAddress { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs b/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs
new file mode 100644
index 0000000..56b8179
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs
@@ -0,0 +1,31 @@
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Информация о процессоре
+///
+public interface IOsProcessorInfo: IOsBasicInfo
+{
+ ///
+ /// Заголовок
+ ///
+
+ ///
+ /// Производитель
+ ///
+ public string? Manufacturer { get; set; }
+
+ ///
+ /// Максимальная тактовая частота
+ ///
+ public int MaxClockSpeed { get; set; }
+
+ ///
+ /// Число ядер
+ ///
+ public int NumberOfCores { get; set; }
+
+ ///
+ /// Число потоков
+ ///
+ public int NumberOfLogicalProcessors { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs b/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs
new file mode 100644
index 0000000..9b4c6a2
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs
@@ -0,0 +1,42 @@
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Информация о видеокарте
+///
+public interface IOsVideoAdapterInfo: IOsBasicInfo
+{
+ ///
+ /// Память
+ ///
+ public int AdapterRAM { get; set; }
+
+ ///
+ /// Текущее разрешение
+ ///
+ public (int, int) CurrentResolution { get; set; }
+
+ ///
+ /// Дата установки драйвера
+ ///
+ public string? DriverDate { get; set; }
+
+ ///
+ /// Версия драйвера
+ ///
+ public string? DriverVersion { get; set; }
+
+ ///
+ /// Название драйверов
+ ///
+ public string? InstalledDisplayDrivers { get; set; }
+
+ ///
+ /// Имя в системе
+ ///
+ public string? SystemName { get; set; }
+
+ ///
+ /// Видео процессор
+ ///
+ public string? VideoProcessor { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs b/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs
new file mode 100644
index 0000000..7459f82
--- /dev/null
+++ b/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs
@@ -0,0 +1,27 @@
+namespace anbs_cp.OsInfo.Interfaces;
+
+///
+/// Информация о Windows
+///
+public interface IOsWindowsInfo: IOsBasicInfo
+{
+ ///
+ /// Версия
+ ///
+ public string? Version { get; set; }
+
+ ///
+ /// 64-разрядная ОС
+ ///
+ public bool Is64 { get; set; }
+
+ ///
+ /// Имя компьютера
+ ///
+ public string? PcName { get; set; }
+
+ ///
+ /// Путь к папке Windows
+ ///
+ public string? WindowsFolder { get; set; }
+}
\ No newline at end of file
diff --git a/anbs_cposinfo/anbs_cposinfo.csproj b/anbs_cposinfo/anbs_cposinfo.csproj
new file mode 100644
index 0000000..45b2409
--- /dev/null
+++ b/anbs_cposinfo/anbs_cposinfo.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net8.0
+ enable
+ enable
+ anbs_cp.OsInfo
+ True
+ ANBSoftware.ComponentsPackOsInfo
+ 2023.11.14
+ Александр Бабаев
+ Набор компонентов ANB Software для получения информации о Windows
+ Библиотека полезных методов языка C# для получения информации об Windows
+ Александр Бабаев
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack
+ git
+
+
+
+
+
+
+
+
+
+
+
diff --git a/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings b/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings
new file mode 100644
index 0000000..632c268
--- /dev/null
+++ b/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp120
\ No newline at end of file
diff --git a/anbsoftware.componentspack.sln b/anbsoftware.componentspack.sln
index adc732b..0760bba 100644
--- a/anbsoftware.componentspack.sln
+++ b/anbsoftware.componentspack.sln
@@ -5,11 +5,17 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cp", "anbs_cp\anbs_cp.csproj", "{442A56CC-1061-4EB5-8B67-3E3D997976D7}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}"
ProjectSection(ProjectDependencies) = postProject
{442A56CC-1061-4EB5-8B67-3E3D997976D7} = {442A56CC-1061-4EB5-8B67-3E3D997976D7}
EndProjectSection
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpfn", "anbs_cpfn\anbs_cpfn.csproj", "{EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cposinfo", "anbs_cposinfo\anbs_cposinfo.csproj", "{80E1FEA9-EEDA-4411-8EBA-11991432E98E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpdb", "anbs_cpdb\anbs_cpdb.csproj", "{3796862F-F181-4A27-92D8-8BF13C4FD711}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -23,6 +29,18 @@ Global
{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.Build.0 = Release|Any CPU
{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Release|Any CPU.ActiveCfg = Debug.CNF|Any CPU
+ {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3796862F-F181-4A27-92D8-8BF13C4FD711}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3796862F-F181-4A27-92D8-8BF13C4FD711}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/anbsoftware.componentspack.sln.DotSettings b/anbsoftware.componentspack.sln.DotSettings
new file mode 100644
index 0000000..94e58b5
--- /dev/null
+++ b/anbsoftware.componentspack.sln.DotSettings
@@ -0,0 +1,30 @@
+
+ CD
+ HD
+ HDD
+ RA
+ RAM
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/demo/CountValueTest.Designer.cs b/demo/CountValueTest.Designer.cs
index 6656a3b..2088b44 100644
--- a/demo/CountValueTest.Designer.cs
+++ b/demo/CountValueTest.Designer.cs
@@ -1,39 +1,40 @@
-namespace demo
+namespace demo;
+
+sealed partial class CountValueTest
{
- partial class CountValueTest
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing)
{
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
+ if (disposing && (components != null))
{
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
+ components.Dispose();
}
+ base.Dispose(disposing);
+ }
- #region Windows Form Designer generated code
+ #region Windows Form Designer generated code
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent ()
+ {
this.InsertDataLabel = new System.Windows.Forms.Label();
this.InsertDataBox = new System.Windows.Forms.TextBox();
this.ResultLabel = new System.Windows.Forms.Label();
this.CalculateButton = new System.Windows.Forms.Button();
this.SelectFormatterLabel = new System.Windows.Forms.Label();
this.SelectFormatterBox = new System.Windows.Forms.ComboBox();
+ this.calculateConvButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// InsertDataLabel
@@ -41,16 +42,17 @@
this.InsertDataLabel.AutoSize = true;
this.InsertDataLabel.Location = new System.Drawing.Point(12, 66);
this.InsertDataLabel.Name = "InsertDataLabel";
- this.InsertDataLabel.Size = new System.Drawing.Size(197, 17);
+ this.InsertDataLabel.Size = new System.Drawing.Size(341, 17);
this.InsertDataLabel.TabIndex = 0;
- this.InsertDataLabel.Text = "&Insert any int value:";
+ this.InsertDataLabel.Text = "&Введите любое целочисленное значение:";
//
// InsertDataBox
//
this.InsertDataBox.Location = new System.Drawing.Point(12, 86);
this.InsertDataBox.Name = "InsertDataBox";
- this.InsertDataBox.Size = new System.Drawing.Size(246, 24);
+ this.InsertDataBox.Size = new System.Drawing.Size(457, 24);
this.InsertDataBox.TabIndex = 1;
+ this.InsertDataBox.TextChanged += new System.EventHandler(this.InsertDataBox_TextChanged);
//
// ResultLabel
//
@@ -59,19 +61,19 @@
this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
this.ResultLabel.Name = "ResultLabel";
this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
- this.ResultLabel.Size = new System.Drawing.Size(270, 79);
+ this.ResultLabel.Size = new System.Drawing.Size(478, 79);
this.ResultLabel.TabIndex = 2;
- this.ResultLabel.Text = "&Insert any int value to insert box above and press \"Calculate\" button to see res" +
- "ult...";
+ this.ResultLabel.Text = "&Вставьте любое целочисленное значение в поле выше и нажмите кнопку \"Вычислить\", " +
+ "чтобы увидеть результат...";
this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// CalculateButton
//
- this.CalculateButton.Location = new System.Drawing.Point(81, 116);
+ this.CalculateButton.Location = new System.Drawing.Point(12, 116);
this.CalculateButton.Name = "CalculateButton";
- this.CalculateButton.Size = new System.Drawing.Size(103, 23);
+ this.CalculateButton.Size = new System.Drawing.Size(234, 23);
this.CalculateButton.TabIndex = 3;
- this.CalculateButton.Text = "Calc&ulate";
+ this.CalculateButton.Text = "В&ычислить обработчиком";
this.CalculateButton.UseVisualStyleBackColor = true;
this.CalculateButton.Click += new System.EventHandler(this.CalculateButton_Click);
//
@@ -80,9 +82,9 @@
this.SelectFormatterLabel.AutoSize = true;
this.SelectFormatterLabel.Location = new System.Drawing.Point(12, 9);
this.SelectFormatterLabel.Name = "SelectFormatterLabel";
- this.SelectFormatterLabel.Size = new System.Drawing.Size(161, 17);
+ this.SelectFormatterLabel.Size = new System.Drawing.Size(188, 17);
this.SelectFormatterLabel.TabIndex = 4;
- this.SelectFormatterLabel.Text = "&Select formatter:";
+ this.SelectFormatterLabel.Text = "В&ыберете обработчик:";
//
// SelectFormatterBox
//
@@ -90,18 +92,29 @@
this.SelectFormatterBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.SelectFormatterBox.FormattingEnabled = true;
this.SelectFormatterBox.Items.AddRange(new object[] {
- "CountFormatter",
- "FileSizeFormatter"});
+ "Обработчик счёта",
+ "Обработчик размера файла"});
this.SelectFormatterBox.Location = new System.Drawing.Point(12, 29);
this.SelectFormatterBox.Name = "SelectFormatterBox";
- this.SelectFormatterBox.Size = new System.Drawing.Size(246, 25);
+ this.SelectFormatterBox.Size = new System.Drawing.Size(457, 25);
this.SelectFormatterBox.TabIndex = 5;
//
+ // calculateConvButton
+ //
+ this.calculateConvButton.Location = new System.Drawing.Point(252, 116);
+ this.calculateConvButton.Name = "calculateConvButton";
+ this.calculateConvButton.Size = new System.Drawing.Size(217, 23);
+ this.calculateConvButton.TabIndex = 6;
+ this.calculateConvButton.Text = "&Вычислить конвертером";
+ this.calculateConvButton.UseVisualStyleBackColor = true;
+ this.calculateConvButton.Click += new System.EventHandler(this.calculateConvButton_Click);
+ //
// CountValueTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(270, 222);
+ this.ClientSize = new System.Drawing.Size(478, 222);
+ this.Controls.Add(this.calculateConvButton);
this.Controls.Add(this.SelectFormatterBox);
this.Controls.Add(this.SelectFormatterLabel);
this.Controls.Add(this.CalculateButton);
@@ -115,20 +128,20 @@
this.Name = "CountValueTest";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
- this.Text = "Formatter Test Unit";
+ this.Text = "Тест модуля форматирования строки";
this.Load += new System.EventHandler(this.CountValueTest_Load);
this.ResumeLayout(false);
this.PerformLayout();
- }
-
- #endregion
-
- private Label InsertDataLabel;
- private TextBox InsertDataBox;
- private Label ResultLabel;
- private Button CalculateButton;
- private Label SelectFormatterLabel;
- private ComboBox SelectFormatterBox;
}
+
+ #endregion
+
+ private Label InsertDataLabel;
+ private TextBox InsertDataBox;
+ private Label ResultLabel;
+ private Button CalculateButton;
+ private Label SelectFormatterLabel;
+ private ComboBox SelectFormatterBox;
+ private Button calculateConvButton;
}
\ No newline at end of file
diff --git a/demo/CountValueTest.cs b/demo/CountValueTest.cs
index defe9b7..4afcb46 100644
--- a/demo/CountValueTest.cs
+++ b/demo/CountValueTest.cs
@@ -1,42 +1,56 @@
-using anbs_cp;
-namespace demo
+using anbs_cp.Classes;
+using anbs_cp.Interfaces;
+
+namespace demo;
+
+public sealed partial class CountValueTest: Form
{
- public partial class CountValueTest : Form
+ public CountValueTest ()
{
- public CountValueTest()
+ InitializeComponent();
+ }
+
+ private void CalculateButton_Click (object sender, EventArgs e)
+ {
+
+ if (string.IsNullOrEmpty(InsertDataBox.Text))
+ return;
+
+ long value = TypeConverter.StrToInt64(InsertDataBox.Text);
+ IValueFormatter formatter = SelectFormatterBox.SelectedIndex switch
{
- InitializeComponent();
- }
+ 0 => new CountFormatter(),
+ 1 => new FileSizeFormatter(),
+ _ => new CountFormatter(),
+ };
+ ResultLabel.Text = formatter.Format(value);
+ }
- private void CalculateButton_Click(object sender, EventArgs e)
+ private void CountValueTest_Load (object sender, EventArgs e)
+ {
+ SelectFormatterBox.SelectedIndex = 0;
+ }
+
+ private void InsertDataBox_TextChanged (object sender, EventArgs e)
+ {
+ ulong value = TypeConverter.StrToUInt64(InsertDataBox.Text);
+
+ if (value > long.MaxValue)
+ InsertDataBox.Text = long.MaxValue.ToString();
+ }
+
+ private void calculateConvButton_Click (object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(InsertDataBox.Text))
+ return;
+
+ long value = TypeConverter.StrToInt64(InsertDataBox.Text);
+
+ ResultLabel.Text = SelectFormatterBox.SelectedIndex switch
{
-
- if (string.IsNullOrEmpty(InsertDataBox.Text))
- return;
-
- IValueFormatter formatter;
-
- long value = TypeConverter.StrToInt64(InsertDataBox.Text);
-
- switch (SelectFormatterBox.SelectedIndex)
- {
- case 0:
- formatter = new CountFormatter();
- break;
- case 1:
- formatter = new FileSizeFormatter();
- break;
- default:
- formatter = new CountFormatter();
- break;
- }
-
- ResultLabel.Text = formatter.Format(value);
- }
-
- private void CountValueTest_Load(object sender, EventArgs e)
- {
- SelectFormatterBox.SelectedIndex = 0;
- }
+ 0 => new CountConverter(CountConverter.DefaultNames).Convert(value),
+ 1 => new FileSizeConverter(FileSizeConverter.DefaultNames).Convert(value),
+ _ => new CountConverter(CountConverter.DefaultNames).Convert(value)
+ };
}
}
\ No newline at end of file
diff --git a/demo/FileHashAndMimeTypeTest.Designer.cs b/demo/FileHashAndMimeTypeTest.Designer.cs
new file mode 100644
index 0000000..bb6e4f9
--- /dev/null
+++ b/demo/FileHashAndMimeTypeTest.Designer.cs
@@ -0,0 +1,125 @@
+namespace demo;
+
+sealed partial class FileHashAndMimeType
+{
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent ()
+ {
+ this.ResultLabel = new System.Windows.Forms.Label();
+ this.SelectFileLabel = new System.Windows.Forms.Label();
+ this.fileNameEdt = new System.Windows.Forms.TextBox();
+ this.ViewButton = new System.Windows.Forms.Button();
+ this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
+ this.topPanel = new System.Windows.Forms.Panel();
+ this.topPanel.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // ResultLabel
+ //
+ this.ResultLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.ResultLabel.Location = new System.Drawing.Point(0, 0);
+ this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
+ this.ResultLabel.Name = "ResultLabel";
+ this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
+ this.ResultLabel.Size = new System.Drawing.Size(412, 428);
+ this.ResultLabel.TabIndex = 2;
+ this.ResultLabel.Text = "В&ыберете файл (введите ипя файла с полным путём вверху или с помощью диалога, на" +
+ "жав \"Обзор\")...";
+ this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // SelectFileLabel
+ //
+ this.SelectFileLabel.AutoSize = true;
+ this.SelectFileLabel.Location = new System.Drawing.Point(3, 11);
+ this.SelectFileLabel.Name = "SelectFileLabel";
+ this.SelectFileLabel.Size = new System.Drawing.Size(134, 17);
+ this.SelectFileLabel.TabIndex = 4;
+ this.SelectFileLabel.Text = "В&ыберете файл:";
+ //
+ // fileNameEdt
+ //
+ this.fileNameEdt.Location = new System.Drawing.Point(3, 38);
+ this.fileNameEdt.Name = "fileNameEdt";
+ this.fileNameEdt.Size = new System.Drawing.Size(288, 24);
+ this.fileNameEdt.TabIndex = 5;
+ this.fileNameEdt.TextChanged += new System.EventHandler(this.fileNameEdt_TextChanged);
+ //
+ // ViewButton
+ //
+ this.ViewButton.Location = new System.Drawing.Point(297, 39);
+ this.ViewButton.Name = "ViewButton";
+ this.ViewButton.Size = new System.Drawing.Size(103, 23);
+ this.ViewButton.TabIndex = 3;
+ this.ViewButton.Text = "&Обзор";
+ this.ViewButton.UseVisualStyleBackColor = true;
+ this.ViewButton.Click += new System.EventHandler(this.ViewButton_Click);
+ //
+ // openFileDialog
+ //
+ this.openFileDialog.AddToRecent = false;
+ this.openFileDialog.Filter = "Все файлы|*.*";
+ this.openFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog_FileOk);
+ //
+ // topPanel
+ //
+ this.topPanel.Controls.Add(this.SelectFileLabel);
+ this.topPanel.Controls.Add(this.ViewButton);
+ this.topPanel.Controls.Add(this.fileNameEdt);
+ this.topPanel.Dock = System.Windows.Forms.DockStyle.Top;
+ this.topPanel.Location = new System.Drawing.Point(0, 0);
+ this.topPanel.Name = "topPanel";
+ this.topPanel.Size = new System.Drawing.Size(412, 74);
+ this.topPanel.TabIndex = 6;
+ //
+ // FileHashAndMimeType
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(412, 428);
+ this.Controls.Add(this.topPanel);
+ this.Controls.Add(this.ResultLabel);
+ this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FileHashAndMimeType";
+ this.ShowIcon = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Получение хэша и MIME-типа файла";
+ this.topPanel.ResumeLayout(false);
+ this.topPanel.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ private Label ResultLabel;
+ private Label SelectFileLabel;
+ private TextBox fileNameEdt;
+ private Button ViewButton;
+ private OpenFileDialog openFileDialog;
+ private Panel topPanel;
+}
\ No newline at end of file
diff --git a/demo/FileHashAndMimeTypeTest.cs b/demo/FileHashAndMimeTypeTest.cs
new file mode 100644
index 0000000..69f7cf4
--- /dev/null
+++ b/demo/FileHashAndMimeTypeTest.cs
@@ -0,0 +1,42 @@
+using anbs_cp.Classes;
+// ReSharper disable LocalizableElement
+
+namespace demo;
+
+public sealed partial class FileHashAndMimeType: Form
+{
+ public FileHashAndMimeType ()
+ {
+ InitializeComponent();
+ }
+
+ private void ViewButton_Click (object sender, EventArgs e)
+ {
+ openFileDialog.ShowDialog();
+ }
+
+private void GetFileHashAndMimeType()
+ {
+ if (string.IsNullOrEmpty(fileNameEdt.Text))
+ {
+ ResultLabel.Text = " !";
+ return;
+ }
+
+ string fileHash = new FileHash(fileNameEdt.Text).ToString();
+ string fileType = FileExtension.MIMEType(fileNameEdt.Text);
+
+ ResultLabel.Text =
+ $" \r\n{fileNameEdt.Text}\r\n :\r\n{fileHash}\r\n :\r\n{fileType}";
+ }
+
+ private void openFileDialog_FileOk (object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ fileNameEdt.Text = openFileDialog.FileName;
+ }
+
+ private void fileNameEdt_TextChanged (object sender, EventArgs e)
+ {
+ GetFileHashAndMimeType();
+ }
+}
\ No newline at end of file
diff --git a/demo/FileHashAndMimeTypeTest.resx b/demo/FileHashAndMimeTypeTest.resx
new file mode 100644
index 0000000..e6275bd
--- /dev/null
+++ b/demo/FileHashAndMimeTypeTest.resx
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/demo/MainMenu.Designer.cs b/demo/MainMenu.Designer.cs
new file mode 100644
index 0000000..a13600a
--- /dev/null
+++ b/demo/MainMenu.Designer.cs
@@ -0,0 +1,102 @@
+namespace demo;
+
+sealed partial class MainMenu
+{
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent ()
+ {
+ this.CountValueTest = new System.Windows.Forms.Button();
+ this.SimpleMapperTest = new System.Windows.Forms.Button();
+ this.FileExtensionTest = new System.Windows.Forms.Button();
+ this.OsInfoBtn = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // CountValueTest
+ //
+ this.CountValueTest.Location = new System.Drawing.Point(12, 12);
+ this.CountValueTest.Name = "CountValueTest";
+ this.CountValueTest.Size = new System.Drawing.Size(337, 53);
+ this.CountValueTest.TabIndex = 0;
+ this.CountValueTest.Text = "Новый тест модуля форматирования строки";
+ this.CountValueTest.UseVisualStyleBackColor = true;
+ this.CountValueTest.Click += new System.EventHandler(this.button1_Click);
+ //
+ // SimpleMapperTest
+ //
+ this.SimpleMapperTest.Location = new System.Drawing.Point(12, 71);
+ this.SimpleMapperTest.Name = "SimpleMapperTest";
+ this.SimpleMapperTest.Size = new System.Drawing.Size(335, 51);
+ this.SimpleMapperTest.TabIndex = 1;
+ this.SimpleMapperTest.Text = "Новый тест модуля SimpleMapper";
+ this.SimpleMapperTest.UseVisualStyleBackColor = true;
+ this.SimpleMapperTest.Click += new System.EventHandler(this.SimpleMapperTest_Click);
+ //
+ // FileExtensionTest
+ //
+ this.FileExtensionTest.Location = new System.Drawing.Point(12, 128);
+ this.FileExtensionTest.Name = "FileExtensionTest";
+ this.FileExtensionTest.Size = new System.Drawing.Size(335, 51);
+ this.FileExtensionTest.TabIndex = 2;
+ this.FileExtensionTest.Text = "Новый тест модуля FileExtension";
+ this.FileExtensionTest.UseVisualStyleBackColor = true;
+ this.FileExtensionTest.Click += new System.EventHandler(this.FileExtensionTest_Click);
+ //
+ // OsInfoBtn
+ //
+ this.OsInfoBtn.Location = new System.Drawing.Point(12, 185);
+ this.OsInfoBtn.Name = "OsInfoBtn";
+ this.OsInfoBtn.Size = new System.Drawing.Size(335, 51);
+ this.OsInfoBtn.TabIndex = 3;
+ this.OsInfoBtn.Text = "Информация о системе";
+ this.OsInfoBtn.UseVisualStyleBackColor = true;
+ this.OsInfoBtn.Click += new System.EventHandler(this.OsInfoBtn_Click);
+ //
+ // MainMenu
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(361, 252);
+ this.Controls.Add(this.OsInfoBtn);
+ this.Controls.Add(this.FileExtensionTest);
+ this.Controls.Add(this.SimpleMapperTest);
+ this.Controls.Add(this.CountValueTest);
+ this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Margin = new System.Windows.Forms.Padding(4);
+ this.Name = "MainMenu";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Главное меню";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Button CountValueTest;
+ private Button SimpleMapperTest;
+ private Button FileExtensionTest;
+ private Button OsInfoBtn;
+}
diff --git a/demo/MainMenu.cs b/demo/MainMenu.cs
new file mode 100644
index 0000000..e4acabc
--- /dev/null
+++ b/demo/MainMenu.cs
@@ -0,0 +1,32 @@
+namespace demo;
+public sealed partial class MainMenu: Form
+{
+ public MainMenu ()
+ {
+ InitializeComponent();
+ }
+
+ private void button1_Click (object sender, EventArgs e)
+ {
+ CountValueTest formCountValueTest = new();
+ formCountValueTest.ShowDialog();
+ }
+
+ private void SimpleMapperTest_Click (object sender, EventArgs e)
+ {
+ SampleMapperTest formSampleMapperTest = new();
+ formSampleMapperTest.ShowDialog();
+ }
+
+ private void FileExtensionTest_Click (object sender, EventArgs e)
+ {
+ FileHashAndMimeType formTest = new();
+ formTest.ShowDialog();
+ }
+
+ private void OsInfoBtn_Click (object sender, EventArgs e)
+ {
+ OsInfoFrm formTest = new();
+ formTest.ShowDialog();
+ }
+}
diff --git a/demo/MainMenu.resx b/demo/MainMenu.resx
new file mode 100644
index 0000000..f298a7b
--- /dev/null
+++ b/demo/MainMenu.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/demo/OsInfoFrm.Designer.cs b/demo/OsInfoFrm.Designer.cs
new file mode 100644
index 0000000..3602c5a
--- /dev/null
+++ b/demo/OsInfoFrm.Designer.cs
@@ -0,0 +1,65 @@
+namespace demo;
+
+sealed partial class OsInfoFrm
+{
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent ()
+ {
+ this.textBox = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // textBox
+ //
+ this.textBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBox.Location = new System.Drawing.Point(0, 0);
+ this.textBox.Multiline = true;
+ this.textBox.Name = "textBox";
+ this.textBox.Size = new System.Drawing.Size(1029, 510);
+ this.textBox.TabIndex = 0;
+ //
+ // OsInfoFrm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1029, 510);
+ this.Controls.Add(this.textBox);
+ this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
+ this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "OsInfoFrm";
+ this.Text = "Информация о системе";
+ this.Load += new System.EventHandler(this.OsInfoFrm_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private TextBox textBox;
+}
\ No newline at end of file
diff --git a/demo/OsInfoFrm.cs b/demo/OsInfoFrm.cs
new file mode 100644
index 0000000..f92bea5
--- /dev/null
+++ b/demo/OsInfoFrm.cs
@@ -0,0 +1,28 @@
+using anbs_cp.OsInfo.Classes;
+
+using Newtonsoft.Json;
+
+namespace demo;
+public sealed partial class OsInfoFrm: Form
+{
+ public OsInfoFrm ()
+ {
+ InitializeComponent();
+ }
+
+ private void OsInfoFrm_Load (object sender, EventArgs e)
+ {
+ textBox.Text = @"Процессор(ы) | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.Processors);
+ textBox.Text += @"Оперативная память | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.RAM);
+ textBox.Text += @"Видеокарта | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.Videos);
+ textBox.Text += @"Диски | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.Drives);
+ textBox.Text += @"Windows | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.Windows);
+ textBox.Text += @"Net | ";
+ textBox.Text += JsonConvert.SerializeObject(OsInfo.Net);
+ }
+}
diff --git a/demo/OsInfoFrm.resx b/demo/OsInfoFrm.resx
new file mode 100644
index 0000000..f298a7b
--- /dev/null
+++ b/demo/OsInfoFrm.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/demo/Program.cs b/demo/Program.cs
index 47c0157..44dabc6 100644
--- a/demo/Program.cs
+++ b/demo/Program.cs
@@ -1,15 +1,14 @@
-namespace demo
+namespace demo;
+
+internal static class Program
{
- internal static class Program
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main ()
{
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- ApplicationConfiguration.Initialize();
- Application.Run(new CountValueTest());
- }
+ ApplicationConfiguration.Initialize();
+ Application.Run(new MainMenu());
}
}
\ No newline at end of file
diff --git a/demo/SampleMapperTest.Designer.cs b/demo/SampleMapperTest.Designer.cs
new file mode 100644
index 0000000..6b6ca92
--- /dev/null
+++ b/demo/SampleMapperTest.Designer.cs
@@ -0,0 +1,189 @@
+namespace demo;
+
+sealed partial class SampleMapperTest
+{
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent ()
+ {
+ this.DemoBoolEdt = new System.Windows.Forms.CheckBox();
+ this.DemoStringEdt = new System.Windows.Forms.TextBox();
+ this.DemoIntEdt = new System.Windows.Forms.NumericUpDown();
+ this.DemoDateTimeEdt = new System.Windows.Forms.DateTimePicker();
+ this.MapBtn = new System.Windows.Forms.Button();
+ this.ResultArea = new System.Windows.Forms.TextBox();
+ this.DemoStringLabel = new System.Windows.Forms.Label();
+ this.DemoIntLabel = new System.Windows.Forms.Label();
+ this.DemoDateTimeLabel = new System.Windows.Forms.Label();
+ this.MapModeEdit = new System.Windows.Forms.ComboBox();
+ this.MapModeLabel = new System.Windows.Forms.Label();
+ ((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).BeginInit();
+ this.SuspendLayout();
+ //
+ // DemoBoolEdt
+ //
+ this.DemoBoolEdt.AutoSize = true;
+ this.DemoBoolEdt.Location = new System.Drawing.Point(32, 144);
+ this.DemoBoolEdt.Name = "DemoBoolEdt";
+ this.DemoBoolEdt.Size = new System.Drawing.Size(65, 25);
+ this.DemoBoolEdt.TabIndex = 0;
+ this.DemoBoolEdt.Text = "Bool";
+ this.DemoBoolEdt.UseVisualStyleBackColor = true;
+ //
+ // DemoStringEdt
+ //
+ this.DemoStringEdt.Location = new System.Drawing.Point(32, 42);
+ this.DemoStringEdt.Name = "DemoStringEdt";
+ this.DemoStringEdt.Size = new System.Drawing.Size(737, 29);
+ this.DemoStringEdt.TabIndex = 1;
+ //
+ // DemoIntEdt
+ //
+ this.DemoIntEdt.Location = new System.Drawing.Point(32, 109);
+ this.DemoIntEdt.Name = "DemoIntEdt";
+ this.DemoIntEdt.Size = new System.Drawing.Size(737, 29);
+ this.DemoIntEdt.TabIndex = 2;
+ //
+ // DemoDateTimeEdt
+ //
+ this.DemoDateTimeEdt.CustomFormat = "dd.MM.yyyy HH:mm:ss";
+ this.DemoDateTimeEdt.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.DemoDateTimeEdt.Location = new System.Drawing.Point(32, 193);
+ this.DemoDateTimeEdt.Name = "DemoDateTimeEdt";
+ this.DemoDateTimeEdt.Size = new System.Drawing.Size(737, 29);
+ this.DemoDateTimeEdt.TabIndex = 3;
+ //
+ // MapBtn
+ //
+ this.MapBtn.Location = new System.Drawing.Point(32, 306);
+ this.MapBtn.Name = "MapBtn";
+ this.MapBtn.Size = new System.Drawing.Size(737, 57);
+ this.MapBtn.TabIndex = 5;
+ this.MapBtn.Text = "СВЯЗАТЬ";
+ this.MapBtn.UseVisualStyleBackColor = true;
+ this.MapBtn.Click += new System.EventHandler(this.MapBtn_Click);
+ //
+ // ResultArea
+ //
+ this.ResultArea.Dock = System.Windows.Forms.DockStyle.Right;
+ this.ResultArea.Location = new System.Drawing.Point(819, 0);
+ this.ResultArea.Multiline = true;
+ this.ResultArea.Name = "ResultArea";
+ this.ResultArea.ReadOnly = true;
+ this.ResultArea.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.ResultArea.Size = new System.Drawing.Size(332, 378);
+ this.ResultArea.TabIndex = 6;
+ //
+ // DemoStringLabel
+ //
+ this.DemoStringLabel.AutoSize = true;
+ this.DemoStringLabel.Location = new System.Drawing.Point(32, 18);
+ this.DemoStringLabel.Name = "DemoStringLabel";
+ this.DemoStringLabel.Size = new System.Drawing.Size(54, 21);
+ this.DemoStringLabel.TabIndex = 7;
+ this.DemoStringLabel.Text = "String";
+ //
+ // DemoIntLabel
+ //
+ this.DemoIntLabel.AutoSize = true;
+ this.DemoIntLabel.Location = new System.Drawing.Point(32, 85);
+ this.DemoIntLabel.Name = "DemoIntLabel";
+ this.DemoIntLabel.Size = new System.Drawing.Size(30, 21);
+ this.DemoIntLabel.TabIndex = 8;
+ this.DemoIntLabel.Text = "Int";
+ //
+ // DemoDateTimeLabel
+ //
+ this.DemoDateTimeLabel.AutoSize = true;
+ this.DemoDateTimeLabel.Location = new System.Drawing.Point(32, 169);
+ this.DemoDateTimeLabel.Name = "DemoDateTimeLabel";
+ this.DemoDateTimeLabel.Size = new System.Drawing.Size(81, 21);
+ this.DemoDateTimeLabel.TabIndex = 9;
+ this.DemoDateTimeLabel.Text = "DateTime";
+ //
+ // MapModeEdit
+ //
+ this.MapModeEdit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.MapModeEdit.FormattingEnabled = true;
+ this.MapModeEdit.Items.AddRange(new object[] {
+ "Full",
+ "Not null",
+ "Not default",
+ "Not null or default"});
+ this.MapModeEdit.Location = new System.Drawing.Point(32, 254);
+ this.MapModeEdit.Name = "MapModeEdit";
+ this.MapModeEdit.Size = new System.Drawing.Size(737, 29);
+ this.MapModeEdit.TabIndex = 10;
+ //
+ // MapModeLabel
+ //
+ this.MapModeLabel.AutoSize = true;
+ this.MapModeLabel.Location = new System.Drawing.Point(32, 230);
+ this.MapModeLabel.Name = "MapModeLabel";
+ this.MapModeLabel.Size = new System.Drawing.Size(167, 21);
+ this.MapModeLabel.TabIndex = 11;
+ this.MapModeLabel.Text = "Режим связывания:";
+ //
+ // SampleMapperTest
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1151, 378);
+ this.Controls.Add(this.MapModeLabel);
+ this.Controls.Add(this.MapModeEdit);
+ this.Controls.Add(this.DemoDateTimeLabel);
+ this.Controls.Add(this.DemoIntLabel);
+ this.Controls.Add(this.DemoStringLabel);
+ this.Controls.Add(this.ResultArea);
+ this.Controls.Add(this.MapBtn);
+ this.Controls.Add(this.DemoDateTimeEdt);
+ this.Controls.Add(this.DemoIntEdt);
+ this.Controls.Add(this.DemoStringEdt);
+ this.Controls.Add(this.DemoBoolEdt);
+ this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.Margin = new System.Windows.Forms.Padding(4);
+ this.Name = "SampleMapperTest";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Тест класса SampleMapper";
+ ((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private CheckBox DemoBoolEdt;
+ private TextBox DemoStringEdt;
+ private NumericUpDown DemoIntEdt;
+ private DateTimePicker DemoDateTimeEdt;
+ private Button MapBtn;
+ private TextBox ResultArea;
+ private Label DemoStringLabel;
+ private Label DemoIntLabel;
+ private Label DemoDateTimeLabel;
+ private ComboBox MapModeEdit;
+ private Label MapModeLabel;
+}
diff --git a/demo/SampleMapperTest.cs b/demo/SampleMapperTest.cs
new file mode 100644
index 0000000..0890aa8
--- /dev/null
+++ b/demo/SampleMapperTest.cs
@@ -0,0 +1,71 @@
+using anbs_cp.Classes;
+using Newtonsoft.Json;
+
+namespace demo;
+public sealed partial class SampleMapperTest: Form
+{
+ public SampleMapperTest ()
+ {
+ InitializeComponent();
+ }
+
+ private void MapBtn_Click (object sender, EventArgs e)
+ {
+ Demo1Class demo1 = new()
+ {
+ DemoString = DemoStringEdt.Text,
+ DemoInt = (int)DemoIntEdt.Value,
+ DemoBool = DemoBoolEdt.Checked,
+ DemoDateTime = DemoDateTimeEdt.Value
+ };
+
+ Demo1Class demo2 = new()
+ {
+ DemoInt = 20220224,
+ DemoBool = true,
+ DemoDateTime = default
+ };
+
+ string serialize1 = JsonConvert.SerializeObject(demo2);
+
+ SimpleMapper.MapMode mode = MapModeEdit.SelectedIndex switch
+ {
+ 0 => SimpleMapper.MapMode.MapFull,
+ 1 => SimpleMapper.MapMode.MapNotNull,
+ 2 => SimpleMapper.MapMode.MapNotDefault,
+ 3 => SimpleMapper.MapMode.MapNotNullOrDefault,
+ _ => SimpleMapper.MapMode.MapFull
+ };
+
+ SimpleMapper.MapEx(demo1, ref demo2, mode, new List());
+
+ string serialize2 = JsonConvert.SerializeObject(demo2);
+
+ // ReSharper disable once LocalizableElement
+ ResultArea.Text = $"Класс Demo2 до связывания:\r\n{serialize1}\r\nи после:\r\n{serialize2}";
+ }
+}
+
+public sealed class Demo1Class
+{
+ public string? DemoString { get; set; }
+
+ public int DemoInt { get; set; }
+
+ public bool DemoBool { get; set; }
+
+ public DateTime DemoDateTime { get; set; }
+}
+
+public class Demo2Class
+{
+ public string? DemoString { get; set; }
+
+ public int DemoInt { get; set; }
+
+ public bool DemoBool { get; set; }
+
+ public DateTime DemoDateTime { get; set; }
+
+ public string? DemoStringNotMapped { get; set; }
+}
\ No newline at end of file
diff --git a/demo/SampleMapperTest.resx b/demo/SampleMapperTest.resx
new file mode 100644
index 0000000..f298a7b
--- /dev/null
+++ b/demo/SampleMapperTest.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/demo/demo.csproj b/demo/demo.csproj
index 10977d6..d547f4c 100644
--- a/demo/demo.csproj
+++ b/demo/demo.csproj
@@ -2,15 +2,31 @@
WinExe
- net6.0-windows
+ net8.0-windows7.0
enable
true
enable
Release;Debug.CNF
+ demo.Program
+
+
+
+ True
+
+
+
+ True
+
+
+
+ Form
+
+
+
\ No newline at end of file
diff --git a/demo/demo.csproj.DotSettings b/demo/demo.csproj.DotSettings
new file mode 100644
index 0000000..632c268
--- /dev/null
+++ b/demo/demo.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp120
\ No newline at end of file