/// <summary> /// Проверить неоходимость обновления и скачать обновление программы. /// Обновление работает так: /// Для того чтобы скачать обновление и обновиться нужно обновление закачать на сервер. /// Обновление exe файлов и других файлов клиента возможно только из рабочей базы данных. /// Обновление из файловой шары или из ресурса в интернете не сделано. /// Закачивает обновление на сервер программа Utility.exe. /// В её коде присаны все файлы, папки, которые нужно закачать на сервер. /// Там же указывается список папок или файлов, котороые подлежат удалению. /// Все файлы закачиваются на сервер в табличку fbaUpdate. В обновлении участвует только одна табличка. /// После этого при запуске Клиент обращается к этой табличку и смотрит, есть ли обновление (проверка по полю Version и CurrentVersion) /// Сравниваеся с текущей версии EXE файла. Если обновить нужно, то все файлы скачиваются клиентом в папку Update, предназначенную для этого. /// Перед скачиванием папка Update очищается полностью. /// Далее клиент запускает файл Updater.exe передавая в параметрах свое имя файла, а сам завершает работу. /// Updater.exe полностью независимый EXE, он независит от других файлов программы. Updater.exe заменяет файлы программы файлами из папки Update, /// Если при копировании происходит ошибка, то он пытается вернуть прежние версии файлов. После копирования он запускает EXE файл, /// имя которого было передано в параметрах, а сам завершает работу. /// Download - true - скачать файлы обновления, false - только получить данные об обновлении. /// ResultUpdate - описание выполненых действий. /// </summary> /// <param name="version"></param> /// <param name="numberUpdate"></param> /// <param name="resultMessage"></param> /// <param name="needUpdate"></param> /// <param name="showMes">false - тихий режим, сообщений пользователю не выдаем. </param> /// <returns>Результат - true - требуется обновить, false - обновление не требуется.</returns> public static bool UpdateDownload(string version, string numberUpdate, out string resultMessage, out bool needUpdate, bool showMes) { resultMessage = ""; DataTable dT1; DataTable dT2; string sqlLocal; long fileSize = 0; var fileCount = 0; var listDelete = new List <string>(); string[] listNotDeleted; //Очищаем полность папку sys.PathUpdate. if (!FBAFile.DirClean(FBAPath.PathUpdate, out listNotDeleted, true)) { needUpdate = false; return(false); } sqlLocal = "select ID, MD5, Path, FullName, ContentType, Operation, Size from fbaUpdate WHERE Version = '" + version + "' ORDER BY Numberupdate, Numberfile; "; sys.SelectDT(DirectionQuery.Remote, sqlLocal, out dT1); if (dT1.Rows.Count == 0) { resultMessage = ""; //Ошибка обновления. Не удается найти последниюю версию приложения!"; needUpdate = false; return(false); } var progress = new FormProgress("Обновление программы", "Получение файлов для обновления", dT1.Rows.Count); if (showMes) { progress.Show(); } for (var i = 0; i < dT1.Rows.Count; i++) { var id = dT1.Value(i, "ID"); var md5Update = dT1.Value(i, "MD5"); var pathValue = dT1.Value(i, "Path"); var fullName = dT1.Value(i, "FullName"); var contentType = dT1.Value(i, "ContentType"); var operationL = dT1.Value(i, "Operation"); var size = dT1.Value(i, "Size"); var fileNameLocal = fullName.Replace(pathValue, FBAPath.PathMain); var FileNameUpdate = fullName.Replace(pathValue, FBAPath.PathUpdate); if (operationL == "DELFILE" || operationL == "DELDIR") { listDelete.Add(operationL + ": " + fullName); } if (operationL == "ADDDIR") { Directory.CreateDirectory(Path.GetDirectoryName(FileNameUpdate)); } if (operationL == "ADDFILE") { var MD5Local = Crypto.FileHashMD5Calc(fileNameLocal); //MD5 локального файла. var MD5Download = Crypto.FileHashMD5Calc(FileNameUpdate); //MD5 уже скаченного ранее файла. //Если рабочий файл не совпадает с обновлением: if (md5Update != MD5Local) { fileSize = fileSize + Convert.ToInt64(size); fileCount = fileCount + 1; //Если MD5 не совпадает между локальным файлом и файлом для обновления, то скачиваем файл. sqlLocal = "SELECT FileData FROM fbaUpdate WHERE ID = " + id; sys.SelectDT(DirectionQuery.Remote, sqlLocal, out dT2); var FileData = dT2.Value("FileData"); Directory.CreateDirectory(Path.GetDirectoryName(FileNameUpdate)); if (!FBAFile.FileWriteFromBase64(FileData, FileNameUpdate, out resultMessage, showMes)) { resultMessage = "Ошибка обновления. Не удается найти последниюю версию приложения!" + Var.CR + resultMessage; needUpdate = false; return(false); } } } if (listDelete.Count > 0) { //Просто сохраняем в список то, что нужно удалить. var fileName = FBAPath.PathUpdate + "ListDelete.txt"; var listStr = string.Join(Var.CR, listDelete.ToArray()); File.WriteAllText(fileName, listStr, Encoding.Default); } if (showMes) { progress.Inc(); } } progress.Dispose(); if (fileCount == 0 && listDelete.Count == 0) { resultMessage = "Обновление не требуется. Все текущие версии файлов совпадают с файлами обновления " + version; needUpdate = false; return(true); } //Если нужно только удалить папки или файлы, то ставим размер обновления 1 кб, //чтобы не пугать пользователя. if (fileSize == 0) { fileSize = 1024; } var ResStr = "Порядковый номер обновления: " + numberUpdate + Var.CR + "Версия: " + version + Var.CR + "Размер обновления: " + FBAFile.GetFileSizeStr(fileSize, true, true) + Var.CR + "Количество файлов и папок: " + (fileCount + listDelete.Count) + Var.CR + "Текущая версия программы: " + Var.ApplicationVersion; resultMessage = "Файлы для обновления скачаны и готовы для установки." + Var.CR + ResStr; needUpdate = true; return(true); //true - обновлять нужно, false - обновление не требуется. }
/// <summary> /// Послать ошибку на сервер. /// </summary> /// <param name="errorMes">Текст ошибки</param> /// <param name="additionalInfo">Дополнительная информация</param> public static bool SendErrorToServer(string errorMes, string additionalInfo) { //Выходим, если делать ничего не нужно. if (!SaveError) { return(false); } //Это для того чтобы если во время работы этого кода возникнет ошибка, не было зацикливания. SaveError = false; try { //Если чтение параметра неудачное, то ничего не делаем. var Params = new string[10]; //Получаем только при первой ошибке. if (ErrorsCount == 0) { if (Param.Load(DirectionQuery.Remote, Var.UserID, "SaveError", true, "User", out Params)) { if (!Params[0].Replace("SaveError=", "").ToBool()) { return(false); } SaveScreenshot = Params[1].Replace("SaveScreenshot=", "").ToBool(); CompressRatio = Params[2].Replace("CompressRatio=", "").ToInt(); SecBetweenSendError = Params[3].Replace("SecBetweenSendError=", "").ToInt(); } } //sys.Error.SaveError true/false: Сохранять ошибку на сервере или нет. Пример: SaveError=true //sys.Error.SaveScreenshot true/false: Сохранять текст ошибки на сервере или нет. Пример: SaveScreenshot=true //sys.Error.CompressRatio int: находится значение степени сжатия скриншота. По умолчанию формат JPEG, степень сжатия 90. Пример: CompressRatio=90 //sys.Error.SecBetweenSendError int: - количество секунд между ошибками. //sys.Error.LastDateTimeSendError datetime: Время последней ошибки. if (sys.GetSecDiff(LastDateTimeSendError, DateTime.Now) < SecBetweenSendError) { SaveError = true; return(false); } string imagebase64 = ""; string screenshoFormat = ""; string screenshotWidth = ""; string screenshotHeight = ""; string screenshotSize = ""; if (SaveScreenshot) { //Получение скриншота screenshoFormat = "WEBP"; screenshotWidth = Screen.PrimaryScreen.Bounds.Width.ToString(); screenshotHeight = Screen.PrimaryScreen.Bounds.Height.ToString(); Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics graphics = Graphics.FromImage(printscreen as Image); graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size); byte[] webpImageData; WebP.EncodeLossly(printscreen, CompressRatio, out webpImageData); imagebase64 = Convert.ToBase64String(webpImageData); screenshotSize = FBAFile.GetFileSizeStr(webpImageData.Length, true, false); } additionalInfo = sys.AddRightCR(additionalInfo); additionalInfo += GetSystemInfo(); string sql = "INSERT INTO fbaError (EntityID, UserID, ErrorTime, ErrorText, ScreenshotFormat, ScreenshotWidth, ScreenshotHeight, ScreenshotSize, " + "CompressRatio, AdditionalInfo, ScreenshotData) VALUES (" + Var.CR + "123, " + Var.UserID + "," + sys.DateTimeCurrent() + ",'" + errorMes + "','" + screenshoFormat + "','" + screenshotWidth + "','" + screenshotHeight + "'," + screenshotSize + ",'" + Error.CompressRatio.ToString() + "','" + additionalInfo + "','" + imagebase64 + "')"; sys.Exec(DirectionQuery.Remote, sql); LastDateTimeSendError = DateTime.Now; } catch { //Ошибку не выдаем. } SaveError = true; return(true); }