Exemplo n.º 1
0
        /// <summary>
        /// Получить доступные части конфигурации
        /// </summary>
        public bool GetAvailableConfig(out ConfigParts configParts)
        {
            try
            {
                configParts = ConfigParts.None;

                foreach (ConfigParts configPart in AllConfigParts)
                {
                    if (Directory.Exists(Path.Combine(Settings.Directory, DirectoryBuilder.GetDirectory(configPart))))
                    {
                        configParts |= configPart;
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                log.WriteException(ex, Localization.UseRussian ?
                                   "Ошибка при получении доступных частей конфигурации" :
                                   "Error getting available parts of the configuration");
                configParts = ConfigParts.None;
                return(false);
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Упаковать директорию
 /// </summary>
 private void PackDir(ZipArchive zipArchive, RelPath relPath, PathDict ignoredPathDict)
 {
     PackDir(zipArchive,
             GetAbsPath(relPath),
             DirectoryBuilder.GetDirectory(relPath.ConfigPart, relPath.AppFolder, '/'),
             ignoredPathDict.GetOrAdd(relPath.ConfigPart, relPath.AppFolder));
 }
Exemplo n.º 3
0
        /// <summary>
        /// Управлять службой
        /// </summary>
        public bool ControlService(ServiceApp serviceApp, ServiceCommand command)
        {
            try
            {
                string batchFileName = Path.Combine(Settings.Directory,
                                                    DirectoryBuilder.GetDirectory(serviceApp), GetServiceBatchFile(command));

                if (File.Exists(batchFileName))
                {
                    Process.Start(new ProcessStartInfo()
                    {
                        FileName        = batchFileName,
                        UseShellExecute = false
                    });
                    return(true);
                }
                else
                {
                    log.WriteError(string.Format(Localization.UseRussian ?
                                                 "Не найден файл для управления службой {0}" :
                                                 "File {0} for service control not found", batchFileName));
                    return(false);
                }
            }
            catch (Exception ex)
            {
                log.WriteException(ex, Localization.UseRussian ?
                                   "Ошибка при управлении службой" :
                                   "Error controlling service");
                return(false);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Check user
        /// </summary>
        /// <remarks>Checks username, password and role</remarks>
        public bool ValidateUser(string username, string password, out string errMsg)
        {
            try {
                // check the number of attempts
                if (validateUserAttemptNum > MaxValidateUserAttempts)
                {
                    errMsg = Localization.UseRussian
                        ? "Превышено количество попыток входа"
                        : "Number of login attempts exceeded";
                    return(false);
                }
                else
                {
                    validateUserAttemptNum++;
                }

                if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
                {
                    // opening user table
                    BaseAdapter baseAdapter = new BaseAdapter();
                    var         userTable   = new DataTable();
                    baseAdapter.FileName = Path.Combine(Settings.Directory,
                                                        DirectoryBuilder.GetDirectory(ConfigParts.Base), "user.dat");
                    baseAdapter.Fill(userTable, false);

                    // search and verification of user information
                    userTable.CaseSensitive = false;
                    DataRow[] rows = userTable.Select(string.Format("Name = '{0}'", username));

                    if (rows.Length > 0)
                    {
                        var row = rows[0];
                        if ((string)row["Password"] == password)
                        {
                            if ((int)row["RoleID"] == BaseValues.Roles.App)
                            {
                                validateUserAttemptNum = 0;
                                errMsg = "";
                                return(true);
                            }
                            else
                            {
                                errMsg = Localization.UseRussian ? "Недостаточно прав" : "Insufficient rights";
                                return(false);
                            }
                        }
                    }
                }

                errMsg = Localization.UseRussian
                    ? "Неверное имя пользователя или пароль"
                    : "Invalid username or password";
                return(false);
            } catch (Exception ex) {
                errMsg = Localization.UseRussian ? "Ошибка при проверке пользователя" : "Error validating user";
                log.WriteException(ex, errMsg);
                return(false);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Распаковать архив конфигурации
        /// </summary>
        public bool UnpackConfig(string srcFileName, ConfigOptions configOptions)
        {
            try
            {
                // удаление существующей конфигурации
                List <RelPath> configPaths = GetConfigPaths(configOptions.ConfigParts);
                PathDict       pathDict    = PrepareIgnoredPaths(configOptions.IgnoredPaths);

                foreach (RelPath relPath in configPaths)
                {
                    ClearDir(relPath, pathDict);
                }

                // определение допустимых директорий для распаковки
                ConfigParts   configParts    = configOptions.ConfigParts;
                List <string> allowedEntries = new List <string>(AllConfigParts.Length);

                foreach (ConfigParts configPart in AllConfigParts)
                {
                    if (configParts.HasFlag(configPart))
                    {
                        allowedEntries.Add(DirectoryBuilder.GetDirectory(configPart, '/'));
                    }
                }

                // распаковка новой конфигурации
                using (FileStream fileStream =
                           new FileStream(srcFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (ZipArchive zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read))
                    {
                        string instanceDir = Settings.Directory;

                        foreach (ZipArchiveEntry entry in zipArchive.Entries)
                        {
                            if (StartsWith(entry.FullName, allowedEntries, StringComparison.Ordinal))
                            {
                                string relPath      = entry.FullName.Replace('/', Path.DirectorySeparatorChar);
                                string destFileName = instanceDir + relPath;
                                Directory.CreateDirectory(Path.GetDirectoryName(destFileName));
                                entry.ExtractToFile(destFileName, true);
                            }
                        }

                        return(true);
                    }
                }
            }
            catch (Exception ex)
            {
                log.WriteException(ex, Localization.UseRussian ?
                                   "Ошибка при распаковке конфигурации из архива" :
                                   "Error unpacking configuration from archive");
                return(false);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Получить статус службы
        /// </summary>
        public bool GetServiceStatus(ServiceApp serviceApp, out ServiceStatus status)
        {
            try
            {
                status = ServiceStatus.Undefined;
                string statusFileName = Path.Combine(Settings.Directory,
                                                     DirectoryBuilder.GetDirectory(serviceApp),
                                                     DirectoryBuilder.GetDirectory(AppFolder.Log),
                                                     GetServiceStatusFile(serviceApp));

                if (File.Exists(statusFileName))
                {
                    string[] lines = File.ReadAllLines(statusFileName, Encoding.UTF8);

                    foreach (string line in lines)
                    {
                        if (line.StartsWith("State", StringComparison.Ordinal) ||
                            line.StartsWith("Состояние", StringComparison.Ordinal))
                        {
                            int colonInd = line.IndexOf(':');

                            if (colonInd > 0)
                            {
                                string statusStr = line.Substring(colonInd + 1).Trim();

                                if (statusStr.Equals("normal", StringComparison.OrdinalIgnoreCase) ||
                                    statusStr.Equals("норма", StringComparison.OrdinalIgnoreCase))
                                {
                                    status = ServiceStatus.Normal;
                                }
                                else if (statusStr.Equals("stopped", StringComparison.OrdinalIgnoreCase) ||
                                         statusStr.Equals("остановлен", StringComparison.OrdinalIgnoreCase))
                                {
                                    status = ServiceStatus.Stopped;
                                }
                                else if (statusStr.Equals("error", StringComparison.OrdinalIgnoreCase) ||
                                         statusStr.Equals("ошибка", StringComparison.OrdinalIgnoreCase))
                                {
                                    status = ServiceStatus.Error;
                                }
                            }
                        }
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                log.WriteException(ex, Localization.UseRussian ?
                                   "Ошибка при получении статуса службы" :
                                   "Error getting service status");
                status = ServiceStatus.Undefined;
                return(false);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Проверить пользователя
        /// </summary>
        /// <remarks>Проверяется имя пользователя, пароль и роль</remarks>
        public bool ValidateUser(string username, string password, out string errMsg)
        {
            try
            {
                // проверка количества попыток
                if (validateUserAttemptNum > MaxValidateUserAttempts)
                {
                    errMsg = Localization.UseRussian ?
                             "Превышено количество попыток входа" :
                             "Number of login attempts exceeded";
                    return(false);
                }

                if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
                {
                    // открытие таблицы пользователей
                    BaseAdapter baseAdapter = new BaseAdapter();
                    DataTable   userTable   = new DataTable();
                    baseAdapter.FileName = Path.Combine(Settings.Directory,
                                                        DirectoryBuilder.GetDirectory(ConfigParts.Base), "user.dat");
                    baseAdapter.Fill(userTable, false);

                    // поиск и проверка информации о пользователе
                    userTable.CaseSensitive = false;
                    DataRow[] rows = userTable.Select(string.Format("Name = '{0}'", username));

                    if (rows.Length > 0)
                    {
                        DataRow row = rows[0];
                        if ((string)row["Password"] == password && (int)row["RoleID"] == BaseValues.Roles.Admin)
                        {
                            validateUserAttemptNum = 0;
                            errMsg = "";
                            return(true);
                        }
                    }
                }

                validateUserAttemptNum++;
                errMsg = Localization.UseRussian ?
                         "Неверное имя пользователя или пароль" :
                         "Invalid username or password";
                return(false);
            }
            catch (Exception ex)
            {
                errMsg = Localization.UseRussian ?
                         "Ошибка при проверке пользователя" :
                         "Error validating user";
                log.WriteException(ex, errMsg);
                return(false);
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Unpack configuration archive
        /// </summary>
        public bool UnpackConfig(string srcFileName, ConfigOptions configOptions)
        {
            try {
                // delete existing configuration
                List <RelPath> configPaths = GetConfigPaths(configOptions.ConfigParts);
                var            pathDict    = PrepareIgnoredPaths(configOptions.IgnoredPaths);

                foreach (var relPath in configPaths)
                {
                    ClearDir(relPath, pathDict);
                }

                // definition of valid unpacking directories
                var configParts    = configOptions.ConfigParts;
                var allowedEntries = new List <string>(AllConfigParts.Length);

                foreach (var configPart in AllConfigParts)
                {
                    if (configParts.HasFlag(configPart))
                    {
                        allowedEntries.Add(DirectoryBuilder.GetDirectory(configPart, '/'));
                    }
                }

                // unpacking new configuration
                using (var fileStream =
                           new FileStream(srcFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    using (var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read)) {
                        string instanceDir = Settings.Directory;

                        foreach (var entry in zipArchive.Entries)
                        {
                            if (StartsWith(entry.FullName, allowedEntries, StringComparison.Ordinal))
                            {
                                string relPath      = entry.FullName.Replace('/', Path.DirectorySeparatorChar);
                                string destFileName = instanceDir + relPath;
                                Directory.CreateDirectory(Path.GetDirectoryName(destFileName));
                                entry.ExtractToFile(destFileName, true);
                            }
                        }

                        return(true);
                    }
                }
            } catch (Exception ex) {
                log.WriteException(ex,
                                   Localization.UseRussian
                        ? "Ошибка при распаковке конфигурации из архива"
                        : "Error unpacking configuration from archive");
                return(false);
            }
        }
        public static HashSet <string> LoadBridgeDefinedTypes(bool forceReload)
        {
            if (!forceReload && bridgeTypes != null)
            {
                return(bridgeTypes);
            }

            bridgeTypes = new HashSet <string>();
            // string text = File.ReadAllText((PathProc.BridgePath + "stub-builder" + "inner" + "BridgeTypes.txt").ToProjectRoot);/
            string text = DirectoryBuilder.GetDirectory("configs")["Text"]["BridgeTypes.txt"];

            string[] lines = text.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            string   ns    = "";

            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];
                if (line.StartsWith("//"))
                {
                    continue;
                }
                if (line[0] == '[')
                {
                    ns = line.Substring(1, line.Length - 2);
                }
                else
                {
                    string name   = line;
                    int    index1 = name.IndexOf('<');
                    if (index1 >= 0)
                    {
                        int index2 = name.IndexOf('>');
                        int tCount = name.Substring(index1 + 1, index2 - index1 - 1).Count((c) => c == ',');
                        name = line.Substring(0, index1) + "`" + (tCount + 1);
                    }
                    bridgeTypes.Add(ns + "." + name);
                }
            }

            return(bridgeTypes);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Exports the configuration to the specified archive.
        /// </summary>
        public void ExportToArchive(string destFileName, ScadaProject project, Instance instance,
                                    TransferSettings transferSettings)
        {
            if (destFileName == null)
            {
                throw new ArgumentNullException("destFileName");
            }
            if (project == null)
            {
                throw new ArgumentNullException("project");
            }
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            FileStream fileStream = null;
            ZipArchive zipArchive = null;

            try {
                fileStream = new FileStream(destFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
                zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create);
                bool ignoreRegKeys = transferSettings.IgnoreRegKeys;

                // add the configuration database to the archive
                if (transferSettings.IncludeBase)
                {
                    foreach (IBaseTable srcTable in project.ConfigBase.AllTables)
                    {
                        string entryName  = "BaseDAT/" + srcTable.Name.ToLowerInvariant() + ".dat";
                        var    tableEntry = zipArchive.CreateEntry(entryName, CompressionLevel.Fastest);

                        using (var entryStream = tableEntry.Open()) {
                            // convert the table to DAT format
                            BaseAdapter baseAdapter = new BaseAdapter()
                            {
                                Stream = entryStream
                            };
                            baseAdapter.Update(srcTable);
                        }
                    }
                }

                // add the interface files to the archive
                if (transferSettings.IncludeInterface)
                {
                    PackDirectory(zipArchive, project.Interface.InterfaceDir,
                                  DirectoryBuilder.GetDirectory(ConfigParts.Interface, '/'), ignoreRegKeys);
                }

                // add the Server settings to the archive
                if (transferSettings.IncludeServer && instance.ServerApp.Enabled)
                {
                    PackDirectory(zipArchive, instance.ServerApp.AppDir,
                                  DirectoryBuilder.GetDirectory(ConfigParts.Server, '/'), ignoreRegKeys);
                }

                // add the Communicator settings to the archive
                if (transferSettings.IncludeServer && instance.ServerApp.Enabled)
                {
                    PackDirectory(zipArchive, instance.CommApp.AppDir,
                                  DirectoryBuilder.GetDirectory(ConfigParts.Comm, '/'), ignoreRegKeys);
                }

                // add the Webstation settings to the archive
                if (transferSettings.IncludeServer && instance.ServerApp.Enabled)
                {
                    PackDirectory(zipArchive, Path.Combine(instance.WebApp.AppDir, "config"),
                                  DirectoryBuilder.GetDirectory(ConfigParts.Web, AppFolder.Config, '/'), ignoreRegKeys);

                    if (!transferSettings.IgnoreWebStorage)
                    {
                        PackDirectory(zipArchive, Path.Combine(instance.WebApp.AppDir, "storage"),
                                      DirectoryBuilder.GetDirectory(ConfigParts.Web, AppFolder.Storage, '/'), ignoreRegKeys);
                    }
                }
            } catch (Exception ex) {
                throw new ScadaException(AdminPhrases.ExportToArchiveError, ex);
            } finally {
                zipArchive?.Dispose();
                fileStream?.Dispose();
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Imports the configuration from the specified archive.
        /// </summary>
        public void ImportArchive(string srcFileName, ScadaProject project, Instance instance,
                                  out ConfigParts foundConfigParts)
        {
            if (srcFileName == null)
            {
                throw new ArgumentNullException("srcFileName");
            }
            if (project == null)
            {
                throw new ArgumentNullException("project");
            }
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            foundConfigParts = ConfigParts.None;
            string extractDir = Path.Combine(Path.GetDirectoryName(srcFileName),
                                             Path.GetFileNameWithoutExtension(srcFileName));

            try {
                // extract the configuration
                ExtractArchive(srcFileName, extractDir);

                // import the configuration database
                string srcBaseDir = Path.Combine(extractDir, DirectoryBuilder.GetDirectory(ConfigParts.Base));

                if (Directory.Exists(srcBaseDir))
                {
                    foundConfigParts |= ConfigParts.Base;

                    foreach (IBaseTable destTable in project.ConfigBase.AllTables)
                    {
                        string datFileName = Path.Combine(srcBaseDir, destTable.Name.ToLowerInvariant() + ".dat");

                        if (File.Exists(datFileName))
                        {
                            try {
                                BaseAdapter baseAdapter = new BaseAdapter()
                                {
                                    FileName = datFileName
                                };
                                var srcTable = new DataTable();
                                baseAdapter.Fill(srcTable, true);
                                ImportBaseTable(srcTable, destTable);
                            } catch (Exception ex) {
                                throw new ScadaException(string.Format(
                                                             AdminPhrases.ImportBaseTableError, destTable.Name), ex);
                            }
                        }
                    }
                }

                // import the interface files
                string srcInterfaceDir = Path.Combine(extractDir, DirectoryBuilder.GetDirectory(ConfigParts.Interface));

                if (Directory.Exists(srcInterfaceDir))
                {
                    foundConfigParts |= ConfigParts.Interface;
                    MergeDirectory(srcInterfaceDir, project.Interface.InterfaceDir);
                }

                // import the Server settings
                if (instance.ServerApp.Enabled)
                {
                    string srcServerDir = Path.Combine(extractDir, DirectoryBuilder.GetDirectory(ConfigParts.Server));

                    if (Directory.Exists(srcServerDir))
                    {
                        foundConfigParts |= ConfigParts.Server;
                        MergeDirectory(srcServerDir, instance.ServerApp.AppDir);

                        if (!instance.ServerApp.LoadSettings(out string errMsg))
                        {
                            throw new ScadaException(errMsg);
                        }
                    }
                }

                // import the Communicator settings
                if (instance.CommApp.Enabled)
                {
                    string srcCommDir = Path.Combine(extractDir, DirectoryBuilder.GetDirectory(ConfigParts.Comm));

                    if (Directory.Exists(srcCommDir))
                    {
                        foundConfigParts |= ConfigParts.Comm;
                        MergeDirectory(srcCommDir, instance.CommApp.AppDir);

                        if (!instance.CommApp.LoadSettings(out string errMsg))
                        {
                            throw new ScadaException(errMsg);
                        }
                    }
                }

                // import the Webstation settings
                if (instance.WebApp.Enabled)
                {
                    string srcWebDir = Path.Combine(extractDir, DirectoryBuilder.GetDirectory(ConfigParts.Web));

                    if (Directory.Exists(srcWebDir))
                    {
                        foundConfigParts |= ConfigParts.Web;
                        MergeDirectory(srcWebDir, instance.WebApp.AppDir);
                    }
                }
            } catch (Exception ex) {
                throw new ScadaException(AdminPhrases.ImportArchiveError, ex);
            } finally {
                // delete the extracted files
                if (Directory.Exists(extractDir))
                {
                    Directory.Delete(extractDir, true);
                }
            }
        }
Exemplo n.º 12
0
 /// <summary>
 /// Получить абсолютный путь из относительного
 /// </summary>
 public string GetAbsPath(ConfigParts configPart, AppFolder appFolder, string path)
 {
     return(Path.Combine(Settings.Directory, DirectoryBuilder.GetDirectory(configPart, appFolder), path));
 }
Exemplo n.º 13
0
        /// <summary>
        /// Exports the configuration to the specified archive.
        /// </summary>
        public void ExportToArchive(string destFileName, ScadaProject project, Instance instance,
                                    UploadSettings uploadSettings)
        {
            if (destFileName == null)
            {
                throw new ArgumentNullException("destFileName");
            }
            if (project == null)
            {
                throw new ArgumentNullException("project");
            }
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }
            if (uploadSettings == null)
            {
                throw new ArgumentNullException("transferSettings");
            }

            FileStream fileStream = null;
            ZipArchive zipArchive = null;

            try
            {
                fileStream = new FileStream(destFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
                zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create);

                List <int> objNums       = uploadSettings.ObjNums;
                bool       filterByObj   = objNums.Count > 0;
                bool       ignoreRegKeys = uploadSettings.IgnoreRegKeys;

                // add the configuration database to the archive
                if (uploadSettings.IncludeBase)
                {
                    foreach (IBaseTable srcTable in project.ConfigBase.AllTables)
                    {
                        string          entryName  = "BaseDAT/" + srcTable.Name.ToLowerInvariant() + ".dat";
                        ZipArchiveEntry tableEntry = zipArchive.CreateEntry(entryName, CompressionLevel.Fastest);

                        using (Stream entryStream = tableEntry.Open())
                        {
                            // filter the source table by objects if needed
                            IBaseTable baseTable = srcTable;

                            if (filterByObj)
                            {
                                if (srcTable.ItemType == typeof(InCnl))
                                {
                                    baseTable = GetFilteredTable <InCnl>(srcTable, objNums);
                                }
                                else if (srcTable.ItemType == typeof(CtrlCnl))
                                {
                                    baseTable = GetFilteredTable <CtrlCnl>(srcTable, objNums);
                                }
                                else if (srcTable.ItemType == typeof(Interface))
                                {
                                    baseTable = GetFilteredTable <Interface>(srcTable, objNums);
                                }
                            }

                            // convert the table to DAT format
                            BaseAdapter baseAdapter = new BaseAdapter()
                            {
                                Stream = entryStream
                            };
                            baseAdapter.Update(baseTable);
                        }
                    }
                }

                // add the interface files to the archive
                if (uploadSettings.IncludeInterface)
                {
                    string interfaceDir = project.Interface.InterfaceDir;
                    string entryPrefix  = DirectoryBuilder.GetDirectory(ConfigParts.Interface, '/');

                    if (filterByObj)
                    {
                        PackFiles(zipArchive, interfaceDir,
                                  GetInterfaceFiles(project.ConfigBase.InterfaceTable, interfaceDir, objNums),
                                  entryPrefix);
                    }
                    else
                    {
                        PackDirectory(zipArchive, interfaceDir, entryPrefix, ignoreRegKeys);
                    }
                }

                // add the Server settings to the archive
                if (uploadSettings.IncludeServer && instance.ServerApp.Enabled)
                {
                    PackDirectory(zipArchive, instance.ServerApp.AppDir,
                                  DirectoryBuilder.GetDirectory(ConfigParts.Server, '/'), ignoreRegKeys);
                }

                // add the Communicator settings to the archive
                if (uploadSettings.IncludeComm && instance.CommApp.Enabled)
                {
                    PackDirectory(zipArchive, instance.CommApp.AppDir,
                                  DirectoryBuilder.GetDirectory(ConfigParts.Comm, '/'), ignoreRegKeys);
                }

                // add the Webstation settings to the archive
                if (uploadSettings.IncludeWeb && instance.WebApp.Enabled)
                {
                    PackDirectory(zipArchive, Path.Combine(instance.WebApp.AppDir, "config"),
                                  DirectoryBuilder.GetDirectory(ConfigParts.Web, AppFolder.Config, '/'), ignoreRegKeys);

                    if (!uploadSettings.IgnoreWebStorage)
                    {
                        PackDirectory(zipArchive, Path.Combine(instance.WebApp.AppDir, "storage"),
                                      DirectoryBuilder.GetDirectory(ConfigParts.Web, AppFolder.Storage, '/'), ignoreRegKeys);
                    }
                }

                // add an information entry to the archive
                using (Stream entryStream =
                           zipArchive.CreateEntry(ProjectInfoEntryName, CompressionLevel.Fastest).Open())
                {
                    using (StreamWriter writer = new StreamWriter(entryStream, Encoding.UTF8))
                    {
                        writer.Write(project.GetInfo());
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ScadaException(AdminPhrases.ExportToArchiveError, ex);
            }
            finally
            {
                zipArchive?.Dispose();
                fileStream?.Dispose();
            }
        }