Esempio n. 1
0
        private bool editMode;           // режим редактирования


        /// <summary>
        /// Конструктор
        /// </summary>
        private FrmSrezTableEdit()
        {
            InitializeComponent();
            errLog = null;
            srezAdapter = null;
            srezTable = null;
            dataTable1 = null;
            dataTable2 = null;
            selSrez = null;
            editMode = false;
        }
Esempio n. 2
0
        /// <summary>
        /// Записать изменения таблицы срезов в файл или поток
        /// </summary>
        public void Update(SrezTable srezTable)
        {
            if (srezTable == null)
            {
                throw new ArgumentNullException("srezTable");
            }

            Stream       stream = null;
            BinaryWriter writer = null;

            try
            {
                stream = ioStream == null ?
                         new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) :
                         ioStream;
                writer = new BinaryWriter(stream);

                // запись изменённых срезов
                foreach (SrezTable.Srez srez in srezTable.ModifiedSrezList)
                {
                    stream.Seek(srez.Position + 8, SeekOrigin.Begin);
                    writer.Write(GetCnlDataBuf(srez.CnlData));
                }

                // установка позиции записи добавленных срезов в поток,
                // восстановление таблицы срезов в случае необходимости
                SrezTable.Srez lastSrez = srezTable.LastStoredSrez;

                if (lastSrez == null)
                {
                    stream.Seek(0, SeekOrigin.Begin);
                }
                else
                {
                    stream.Seek(0, SeekOrigin.End);
                    long offset = lastSrez.Position + lastSrez.CnlNums.Length * 9 + 8;

                    if (stream.Position < offset)
                    {
                        byte[] buf = new byte[offset - stream.Position];
                        stream.Write(buf, 0, buf.Length);
                    }
                    else
                    {
                        stream.Seek(offset, SeekOrigin.Begin);
                    }
                }

                // запись добавленных срезов
                SrezTable.SrezDescr prevSrezDescr = lastSrez == null ? null : lastSrez.SrezDescr;

                foreach (SrezTable.Srez srez in srezTable.AddedSrezList)
                {
                    // запись номеров каналов среза
                    if (srez.SrezDescr.Equals(prevSrezDescr))
                    {
                        writer.Write(EmptyCnlNumsBuf);
                    }
                    else
                    {
                        writer.Write(GetSrezDescrBuf(srez.SrezDescr));
                    }

                    prevSrezDescr = srez.SrezDescr;

                    // запись данных среза
                    srez.Position = stream.Position;
                    writer.Write(Arithmetic.EncodeDateTime(srez.DateTime));
                    writer.Write(GetCnlDataBuf(srez.CnlData));
                    lastSrez = srez;
                }

                // подтверждение успешного сохранения изменений
                srezTable.AcceptChanges();
                srezTable.LastStoredSrez = lastSrez;
            }
            finally
            {
                if (fileMode)
                {
                    if (writer != null)
                    {
                        writer.Close();
                    }
                    if (stream != null)
                    {
                        stream.Close();
                    }
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Заполнить объект dest из файла срезов FileName
        /// </summary>
        protected void FillObj(object dest)
        {
            Stream       stream   = null;
            BinaryReader reader   = null;
            DateTime     fillTime = DateTime.Now;

            SrezTableLight srezTableLight = dest as SrezTableLight;
            DataTable      dataTable      = dest as DataTable;
            Trend          trend          = dest as Trend;

            SrezTable srezTable = srezTableLight as SrezTable;

            SrezTableLight.Srez lastStoredSrez = null;

            try
            {
                if (srezTableLight == null && dataTable == null && trend == null)
                {
                    throw new Exception("Destination object is invalid.");
                }

                // подготовка объекта для хранения данных
                if (srezTableLight != null)
                {
                    srezTableLight.Clear();
                    srezTableLight.TableName = tableName;

                    if (srezTable != null)
                    {
                        srezTable.BeginLoadData();
                    }
                }
                else if (dataTable != null)
                {
                    // формирование структуры таблицы
                    dataTable.BeginLoadData();
                    dataTable.DefaultView.Sort = "";

                    if (dataTable.Columns.Count == 0)
                    {
                        dataTable.Columns.Add("DateTime", typeof(DateTime));
                        dataTable.Columns.Add("CnlNum", typeof(int));
                        dataTable.Columns.Add("Val", typeof(double));
                        dataTable.Columns.Add("Stat", typeof(int));
                        dataTable.DefaultView.AllowNew    = false;
                        dataTable.DefaultView.AllowEdit   = false;
                        dataTable.DefaultView.AllowDelete = false;
                    }
                    else
                    {
                        dataTable.Rows.Clear();
                    }
                }
                else // trend != null
                {
                    trend.Clear();
                    trend.TableName = tableName;
                }

                // заполнение объекта данными
                stream = ioStream == null ?
                         new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) :
                         ioStream;
                reader = new BinaryReader(stream);

                DateTime            date      = Arithmetic.ExtractDate(tableName); // определение даты срезов
                SrezTable.SrezDescr srezDescr = null;                              // описание среза
                int[] cnlNums = null;                                              // ссылка на номера входных каналов из описания среза
                while (stream.Position < stream.Length)
                {
                    // считывание списка номеров каналов и КС
                    int cnlNumCnt = reader.ReadUInt16();
                    if (cnlNumCnt > 0)
                    {
                        // загрузка номеров каналов в буфер для увеличения скорости работы
                        int    cnlNumSize = cnlNumCnt * 2;
                        byte[] buf        = new byte[cnlNumSize];
                        int    readSize   = reader.Read(buf, 0, cnlNumSize);

                        // создание описания среза и заполнение номеров каналов из буфера
                        // с проверкой их уникальности и упорядоченности
                        if (readSize == cnlNumSize)
                        {
                            int prevCnlNum = -1;
                            srezDescr = new SrezTable.SrezDescr(cnlNumCnt);
                            cnlNums   = srezDescr.CnlNums;
                            for (int i = 0; i < cnlNumCnt; i++)
                            {
                                int cnlNum = BitConverter.ToUInt16(buf, i * 2);
                                if (prevCnlNum >= cnlNum)
                                {
                                    throw new Exception("Table is incorrect.");
                                }
                                cnlNums[i] = prevCnlNum = cnlNum;
                            }
                            srezDescr.CalcCS();
                        }
                    }
                    else if (srezDescr == null)
                    {
                        throw new Exception("Table is incorrect.");
                    }

                    // считывание и проверка КС
                    ushort cs   = reader.ReadUInt16();
                    bool   csOk = cnlNumCnt > 0 ? srezDescr.CS == cs : cs == 1;

                    // считывание данных среза
                    int cnlCnt       = cnlNums.Length; // количество каналов в срезе
                    int srezDataSize = cnlCnt * 9;     // размер данных среза
                    if (csOk)
                    {
                        long   srezPos = stream.Position;
                        double time = reader.ReadDouble();
                        int    hour, min, sec;
                        Arithmetic.DecodeTime(time, out hour, out min, out sec);
                        DateTime srezDT = new DateTime(date.Year, date.Month, date.Day, hour, min, sec);

                        // инициализация нового среза
                        SrezTableLight.Srez srez;
                        if (srezTable != null)
                        {
                            srez = new SrezTable.Srez(srezDT, srezDescr)
                            {
                                State    = DataRowState.Unchanged,
                                Position = srezPos
                            };
                        }
                        else if (srezTableLight != null)
                        {
                            srez = new SrezTableLight.Srez(srezDT, cnlCnt);
                            cnlNums.CopyTo(srez.CnlNums, 0);
                        }
                        else // srezTableLight == null
                        {
                            srez = null;
                        }

                        // считывание данных входных каналов
                        int    bufInd = 0;
                        double val;
                        byte   stat;
                        if (trend != null)
                        {
                            // выбор данных требуемого канала для тренда
                            int index = Array.BinarySearch <int>(cnlNums, trend.CnlNum);
                            if (index >= 0)
                            {
                                stream.Seek(index * 9, SeekOrigin.Current);
                                byte[] buf      = new byte[9];
                                int    readSize = reader.Read(buf, 0, 9);
                                if (readSize == 9)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);
                                    Trend.Point point = new Trend.Point(srezDT, val, stat);
                                    trend.Points.Add(point);
                                    stream.Seek(srezDataSize - (index + 1) * 9, SeekOrigin.Current);
                                }
                            }
                            else
                            {
                                stream.Seek(srezDataSize, SeekOrigin.Current);
                            }
                        }
                        else
                        {
                            // загрузка данных среза в буфер для увеличения скорости работы
                            byte[] buf      = new byte[srezDataSize];
                            int    readSize = reader.Read(buf, 0, srezDataSize);

                            // заполение таблицы срезов из буфера
                            if (srezTableLight != null)
                            {
                                for (int i = 0; i < cnlCnt; i++)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);

                                    srez.CnlNums[i]      = cnlNums[i];
                                    srez.CnlData[i].Val  = val;
                                    srez.CnlData[i].Stat = stat;

                                    if (bufInd >= readSize)
                                    {
                                        break;
                                    }
                                }

                                srezTableLight.AddSrez(srez);
                                lastStoredSrez = srez;
                            }
                            else // dataTable != null
                            {
                                for (int i = 0; i < cnlCnt; i++)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);

                                    DataRow row = dataTable.NewRow();
                                    row["DateTime"] = srezDT;
                                    row["CnlNum"]   = cnlNums[i];
                                    row["Val"]      = val;
                                    row["Stat"]     = stat;
                                    dataTable.Rows.Add(row);

                                    if (bufInd >= readSize)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // пропустить срез, считая его размер так, как при повторяющемся списке номеров каналов
                        stream.Seek(srezDataSize + 8, SeekOrigin.Current);
                    }
                }
            }
            catch (EndOfStreamException)
            {
                // нормальная ситуация окончания файла
            }
            catch
            {
                fillTime = DateTime.MinValue;
                throw;
            }
            finally
            {
                if (fileMode)
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                    if (stream != null)
                    {
                        stream.Close();
                    }
                }

                if (srezTableLight != null)
                {
                    srezTableLight.LastFillTime = fillTime;
                    if (srezTable != null)
                    {
                        srezTable.LastStoredSrez = (SrezTable.Srez)lastStoredSrez;
                        srezTable.EndLoadData();
                    }
                }
                else if (dataTable != null)
                {
                    dataTable.EndLoadData();
                    dataTable.AcceptChanges();
                    dataTable.DefaultView.Sort = "DateTime, CnlNum";
                }
                else if (trend != null)
                {
                    trend.LastFillTime = fillTime;
                    trend.Sort();
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Записать принятый срез в таблицу архивных срезов
        /// </summary>
        private bool WriteReceivedSrez(SrezTable srezTable, SrezAdapter srezAdapter,
            SrezTableLight.Srez receivedSrez, DateTime srezDT, ref SrezTableLight.Srez arcSrez)
        {
            string fileName = "";

            try
            {
                // получение существующего или создание нового архивного среза
                fileName = srezAdapter.FileName;
                SrezTableCache.FillSrezTable(srezTable, srezAdapter);
                SrezTable.Srez srez = srezTable.GetSrez(srezDT);
                bool addSrez;

                if (srez == null)
                {
                    srez = new SrezTable.Srez(srezDT, srezDescr, receivedSrez);
                    addSrez = true;
                }
                else
                {
                    addSrez = false;
                }

                if (arcSrez == null)
                    arcSrez = srez;

                // изменение архивного среза
                lock (calculator)
                {
                    try
                    {
                        procSrez = srez;
                        int cntCnt = receivedSrez.CnlNums.Length;

                        for (int i = 0; i < cntCnt; i++)
                        {
                            int cnlNum = receivedSrez.CnlNums[i];
                            int cnlInd = srez.GetCnlIndex(cnlNum);
                            InCnl inCnl;

                            if (inCnls.TryGetValue(cnlNum, out inCnl) && cnlInd >= 0 &&
                                (inCnl.CnlTypeID == BaseValues.CnlTypes.TS || inCnl.CnlTypeID == BaseValues.CnlTypes.TI))
                            {
                                // вычисление новых данных входного канала
                                SrezTableLight.CnlData oldCnlData = srez.CnlData[cnlInd];
                                SrezTableLight.CnlData newCnlData = receivedSrez.CnlData[i];
                                if (newCnlData.Stat == BaseValues.CnlStatuses.Defined)
                                    newCnlData.Stat = BaseValues.CnlStatuses.Archival;
                                CalcCnlData(inCnl, oldCnlData, ref newCnlData);

                                // запись новых данных в архивный срез
                                srez.CnlData[cnlInd] = newCnlData;
                            }
                        }
                    }
                    finally
                    {
                        procSrez = null;
                    }
                }

                // вычисление дорасчётных каналов
                CalcDRCnls(drCnls, srez, false);

                if (addSrez)
                    srezTable.AddSrez(srez);
                else
                    srezTable.MarkSrezAsModified(srez);

                // запись изменений таблицы срезов
                srezAdapter.Update(srezTable);
                srezTable.FileModTime = File.GetLastWriteTime(fileName);
                return true;
            }
            catch (Exception ex)
            {
                string fileNameStr = string.IsNullOrEmpty(fileName) ? "" :
                    Environment.NewLine + (Localization.UseRussian ? "Имя файла: " : "Filename: ") + fileName;
                AppLog.WriteAction(string.Format(Localization.UseRussian ?
                    "Ошибка при записи принятого среза в таблицу архивных срезов: {0}{1}" :
                    "Error writing received snapshot in the archive data table: {0}{1}",
                    ex.Message, fileNameStr), Log.ActTypes.Exception);
                return false;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Записать срез в таблицу архивных (минутных или часовых) срезов
        /// </summary>
        private void WriteArcSrez(SrezTable srezTable, SrezAdapter srezAdapter, DateTime srezDT, AvgData[] avgData)
        {
            string fileName = "";

            try
            {
                // заполнение таблицы срезов, если файл изменился
                fileName = srezAdapter.FileName;
                SrezTableCache.FillSrezTable(srezTable, srezAdapter);

                // добавление копии среза в таблицу
                SrezTable.Srez newSrez = srezTable.AddSrezCopy(curSrez, srezDT);

                // запись усредняемых данных
                bool changed = false;

                foreach (int cnlInd in avgCnlInds)
                {
                    AvgData ad = avgData[cnlInd];

                    if (ad.Cnt > 0)
                    {
                        newSrez.CnlData[cnlInd] =
                            new SrezTableLight.CnlData(ad.Sum / ad.Cnt, BaseValues.CnlStatuses.Defined);
                        avgData[cnlInd] = new AvgData() { Sum = 0.0, Cnt = 0 }; // сброс
                        changed = true;
                    }
                }

                // вычисление дорасчётных каналов, если добавленый срез изменился
                if (changed)
                    CalcDRCnls(drCnls, newSrez, false);

                // запись изменений таблицы срезов
                srezAdapter.Update(srezTable);
                srezTable.FileModTime = File.GetLastWriteTime(fileName);

                if (Settings.DetailedLog)
                    AppLog.WriteAction(string.Format(Localization.UseRussian ?
                        "Запись среза в таблицу {0} завершена" : "Writing snapshot in the {0} table is completed",
                        srezTable.Descr), Log.ActTypes.Action);
            }
            catch (Exception ex)
            {
                string fileNameStr = string.IsNullOrEmpty(fileName) ? "" :
                    Environment.NewLine + (Localization.UseRussian ? "Имя файла: " : "Filename: ") + fileName;
                AppLog.WriteAction(string.Format(Localization.UseRussian ?
                    "Ошибка при записи среза в таблицу архивных срезов: {0}{1}" :
                    "Error writing snapshot in the archive data table: {0}{1}",
                    ex.Message, fileNameStr), Log.ActTypes.Exception);
            }
        }
Esempio n. 6
0
            /// <summary>
            /// Заполнить таблицу срезов
            /// </summary>
            public static void FillSrezTable(SrezTable srezTable, SrezAdapter srezAdapter)
            {
                string fileName = srezAdapter.FileName;

                if (File.Exists(fileName))
                {
                    // определение времени последнего изменения файла таблицы срезов
                    DateTime fileModTime = File.GetLastWriteTime(fileName);

                    // загрузка данных, если файл был изменён
                    if (srezTable.FileModTime != fileModTime)
                    {
                        srezAdapter.Fill(srezTable);
                        srezTable.FileModTime = fileModTime;
                    }
                }
                else
                {
                    srezTable.Clear();
                }
            }
Esempio n. 7
0
 /// <summary>
 /// Конструктор
 /// </summary>
 public SrezTableCache(DateTime date)
 {
     AccessDT = DateTime.Now;
     Date = date;
     SrezTable = new SrezTable();
     SrezTableCopy = new SrezTable();
     SrezAdapter = new SrezAdapter();
     SrezCopyAdapter = new SrezAdapter();
 }
Esempio n. 8
0
        /// <summary>
        /// Получить буфер описания структуры среза в формате сохранения
        /// </summary>
        protected byte[] GetSrezDescrBuf(SrezTable.SrezDescr srezDescr)
        {
            ushort cnlNumsLen = (ushort)srezDescr.CnlNums.Length;
            byte[] cnlNumsBuf = new byte[cnlNumsLen * 2 + 4];
            cnlNumsBuf[0] = (byte)(cnlNumsLen % 256);
            cnlNumsBuf[1] = (byte)(cnlNumsLen / 256);
            int bufPos = 2;

            for (int i = 0; i < cnlNumsLen; i++)
            {
                ushort cnlNum = (ushort)srezDescr.CnlNums[i];
                cnlNumsBuf[bufPos++] = (byte)(cnlNum % 256);
                cnlNumsBuf[bufPos++] = (byte)(cnlNum / 256);
            }

            cnlNumsBuf[bufPos++] = (byte)(srezDescr.CS % 256);
            cnlNumsBuf[bufPos++] = (byte)(srezDescr.CS / 256);

            return cnlNumsBuf;
        }
Esempio n. 9
0
        /// <summary>
        /// Получить буфер данных среза в формате сохранения
        /// </summary>
        protected byte[] GetCnlDataBuf(SrezTable.CnlData[] cnlData)
        {
            int cnlCnt = cnlData.Length;
            byte[] srezDataBuf = new byte[cnlCnt * 9];

            for (int i = 0, k = 0; i < cnlCnt; i++)
            {
                SrezTable.CnlData data = cnlData[i];
                BitConverter.GetBytes(data.Val).CopyTo(srezDataBuf, k);
                srezDataBuf[k + 8] = (byte)data.Stat;
                k += 9;
            }

            return srezDataBuf;
        }
Esempio n. 10
0
        /// <summary>
        /// Записать изменения таблицы срезов в файл или поток
        /// </summary>
        public void Update(SrezTable srezTable)
        {
            if (srezTable == null)
                throw new ArgumentNullException("srezTable");

            Stream stream = null;
            BinaryWriter writer = null;

            try
            {
                stream = ioStream == null ?
                   new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) :
                   ioStream;
                writer = new BinaryWriter(stream);

                // запись изменённых срезов
                foreach (SrezTable.Srez srez in srezTable.ModifiedSrezList)
                {
                    stream.Seek(srez.Position + 8, SeekOrigin.Begin);
                    writer.Write(GetCnlDataBuf(srez.CnlData));
                }

                // установка позиции записи добавленных срезов в поток,
                // восстановление таблицы срезов в случае необходимости
                SrezTable.Srez lastSrez = srezTable.LastStoredSrez;

                if (lastSrez == null)
                {
                    stream.Seek(0, SeekOrigin.Begin);
                }
                else
                {
                    stream.Seek(0, SeekOrigin.End);
                    long offset = lastSrez.Position + lastSrez.CnlNums.Length * 9 + 8;

                    if (stream.Position < offset)
                    {
                        byte[] buf = new byte[offset - stream.Position];
                        stream.Write(buf, 0, buf.Length);
                    }
                    else
                    {
                        stream.Seek(offset, SeekOrigin.Begin);
                    }
                }

                // запись добавленных срезов
                SrezTable.SrezDescr prevSrezDescr = lastSrez == null ? null : lastSrez.SrezDescr;

                foreach (SrezTable.Srez srez in srezTable.AddedSrezList)
                {
                    // запись номеров каналов среза
                    if (srez.SrezDescr.Equals(prevSrezDescr))
                        writer.Write(EmptyCnlNumsBuf);
                    else
                        writer.Write(GetSrezDescrBuf(srez.SrezDescr));

                    prevSrezDescr = srez.SrezDescr;

                    // запись данных среза
                    srez.Position = stream.Position;
                    writer.Write(Arithmetic.EncodeDateTime(srez.DateTime));
                    writer.Write(GetCnlDataBuf(srez.CnlData));
                    lastSrez = srez;
                }

                // подтверждение успешного сохранения изменений
                srezTable.AcceptChanges();
                srezTable.LastStoredSrez = lastSrez;
            }
            finally
            {
                if (fileMode)
                {
                    if (writer != null)
                        writer.Close();
                    if (stream != null)
                        stream.Close();
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Создать таблицу, состоящую из одного среза, в файле или потоке
        /// </summary>
        /// <remarks>Для записи таблицы текущего среза</remarks>
        public void Create(SrezTable.Srez srez, DateTime srezDT)
        {
            if (srez == null)
                throw new ArgumentNullException("srez");

            Stream stream = null;
            BinaryWriter writer = null;

            try
            {
                stream = ioStream == null ?
                   new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) :
                   ioStream;
                writer = new BinaryWriter(stream);

                writer.Write(GetSrezDescrBuf(srez.SrezDescr));
                writer.Write(Arithmetic.EncodeDateTime(srezDT));
                writer.Write(GetCnlDataBuf(srez.CnlData));
                stream.SetLength(stream.Position);
            }
            finally
            {
                if (fileMode)
                {
                    if (writer != null)
                        writer.Close();
                    if (stream != null)
                        stream.Close();
                }
            }
        }
Esempio n. 12
0
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            // перезагрузка таблицы
            SrezTable newSrezTable = new SrezTable();

            if (LoadSrezTable(srezAdapter, errLog, ref newSrezTable))
            {
                srezTable = newSrezTable;
                FillDataTable1();
                try { dataTable2.DefaultView.RowFilter = txtFilter.Text; }
                catch { txtFilter.Text = ""; }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Отобразить форму редактирования или просмотра таблицы срезов
        /// </summary>
        public static void Show(string directory, string tableName, bool editMode, Log errLog)
        {
            if (string.IsNullOrEmpty(directory))
                throw new ArgumentException("directory");
            if (string.IsNullOrEmpty(tableName))
                throw new ArgumentException("tableName");
            if (errLog == null)
                throw new ArgumentNullException("errLog");

            SrezAdapter srezAdapter = new SrezAdapter();
            srezAdapter.Directory = directory;
            srezAdapter.TableName = tableName;
            SrezTable srezTable = new SrezTable();

            if (LoadSrezTable(srezAdapter, errLog, ref srezTable))
            {
                FrmSrezTableEdit frmSrezTableEdit = new FrmSrezTableEdit();
                frmSrezTableEdit.errLog = errLog;
                frmSrezTableEdit.srezAdapter = srezAdapter;
                frmSrezTableEdit.srezTable = srezTable;
                frmSrezTableEdit.editMode = editMode;
                frmSrezTableEdit.ShowDialog();
            }
        }
Esempio n. 14
0
 /// <summary>
 /// Загрузить таблицу срезов
 /// </summary>
 private static bool LoadSrezTable(SrezAdapter srezAdapter, Log errLog, ref SrezTable srezTable)
 {
     try
     {
         srezAdapter.Fill(srezTable);
         return true;
     }
     catch (Exception ex)
     {
         string errMsg = AppPhrases.LoadSrezTableError + ":\r\n" + ex.Message;
         if (errLog != null)
             errLog.WriteAction(errMsg, Log.ActTypes.Exception);
         ScadaUtils.ShowError(errMsg);
         return false;
     }
     finally
     {
         Cursor.Current = Cursors.Default;
     }
 }