(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Автообновление программы через MSSQL server

Источник: habrahabr
Zerpico

Дабы не бегать по своей работе к каждому человеку который использует мою программу разумно сделать автообновление, которое будет обновлять программу, если загрузить новую версию на сервер. Испробовав множество способов, нашел самый простой в использовании (хотя и не самый правильный)
Итак алгоритм:

  1. Программа при включении проверяет на сервере последнюю версию.
  2. Если на сервере выше текушей то скачиваем Zip-архив c программой.
  3. Переименовываем файл приложения на другое (ради бэкапа и доступности к файлу), например с program.exe на program.backup.
  4. Распаковываем архив заменяя файлы в папке.
  5. Удаляем архив с обновлением.
  6. Перезапускам программу.


Но перед всем этим сначала создадим таблицу Updater (например) на MSSQL с полями:
name - тип varchar;
version -тип varchar;
files - тип varbinary(max) (или любое другое blob-поле).
Лучше сразу создать в таблице запись, где в поле name будет program.
Добавить эту процедуру в код для извлечения номера версии программы:

function TForm1.GetMyVersion: string;
type
  TVerInfo=packed record
    Nevazhno: array[0..47] of byte; // ненужные нам 48 байт
    Minor,Major,Build,Release: word; // а тут версия
  end;
var
  s:TResourceStream;
  v:TVerInfo;
begin
  result:='';
  try
    s:=TResourceStream.Create(HInstance,'#1',RT_VERSION); // достаём ресурс
    if s.Size>0 then begin
      s.Read(v,SizeOf(v)); // читаем нужные нам байты
      result:=IntToStr(v.Major)+IntToStr(v.Minor)+ // вот и версия...
              IntToStr(v.Release)+IntToStr(v.Build);
    end;
  s.Free;
  except; end;
end;

Теперь нам понадобится библиотека для распаковки архивов, ведь я буду хранить обновление в zip архиве, использую библиотеку SevenZip, добавляем в Delphi в library путь до исходников библиотеки.
Теперь нам надо закачать сам архив с новой версией программы в базу данных. Я сделал форму с загрузкой обновления на сервер:
image
по открытию OpenDialog думаю всё понятно переписываем путь в edit

if OpenDialog1.Execute then
cxButtonEdit1.Text:=OpenDialog1.FileName;

Номер версии лучше вписывать в MaskEdit с маской - !9.9.9.0;1;_
По кнопке сохранить закачиваем файл процедурой:

var blobF: TBlobField;
begin
if not FileExists(OpenDialog1.FileName) then
 begin
  ShowMessage('Файл не найден!');
  exit;
 end else cxButtonEdit1.Text:=OpenDialog1.FileName;

try

  ADOTable1.TableName:=Updater; //выбираем таблицу в которой будем хранить архив
  ADOTable1.Close;
  ADOTable1.Open;
  //ищем поле name с записью program
  ADOTable1.Filtered := False;
  ADOTable1.Filter := 'name='+#39+'program'+#39; 
  ADOTable1.Filtered := True;
  ADOTable1.Edit;

  blobF := ADOTable1.FieldByName('files') as TBlobField;
  blobF.LoadFromFile(OpenDialog1.FileName);
  ADOTable1.FieldByName('version').AsString:=cxMaskEdit1.Text;
  ADOTable1.Post;
except
   Showmessage('Ошибка загрузки!');
end;

Это немного неправильный метод, лучше всего сделать отдельным потоком, особенно если архив большого размера.

Необходимо добавить в Uses - SevenZip и ShellAPI.
Теперь создадим самую важную процедуру обновления, назовав её Update:

Procedure TForm1.Update;
var path,fullpath,Ourversion,LastVersion:string;
blobF: TBlobField;
begin
//получем номер версии на сервере
adoquery4.Active:=false;
adoquery4.sql.text:='SELECT version FROM [dbo].[Updater] WHERE name='+#39+'program'+#39;
adoquery4.Active:=true;

//добавляем номера версии на сервере и текушей в переменые, и убираем точки
Ourversion:=GetMyVersion;

LastVersion:=adoquery4.FieldByName('version').Value;
while pos('.',LastVersion)<>0 do
delete(LastVersion,pos('.',LastVersion),1);

//сравниваем версии если текушая меньше чем на сервере то спрашиваем обновлять или нет
if strtoint(LastVersion)>strtoint(Ourversion) then
If messageBox(Handle,'Появилось свежая версия программы. Обновить?','Обновить?',
mb_YesNo or mb_iconquestion)=mrYes then

 try
  path:=ExtractFileDir(ParamStr(0));
  if  FileExists(path+'\Program.backup') then DeleteFile(path+'\Project2.backup');
  RenameFile(path+'\Program.exe', path+'\Program.backup'); //переменовываем оригинальный файл
  //фильтруем
  //ADOTable1 указывает на таблицу Updater
  ADOTable1.Close;
  ADOTable1.Open;
  ADOTable1.Filtered := False;
  ADOTable1.Filter := 'name='+#39+'program'+#39;
  ADOTable1.Filtered := True;
  ADOTable1.Active:=true;
  //скачиваем файл
  blobF := ADOTable1.FieldByName('files') as TBlobField;
  if blobF.Value = nil then Exit;
  blobF.SaveToFile(path+'\Update_ARMTitan.zip');
  ADOTable1.Active:=false;

  // Распаковывает файлы
  with CreateInArchive(CLSID_CFormatZip) do
   begin
     OpenFile(ExtractFilePath(ParamStr(0)) + 'Update_ARMTitan.zip');
     ExtractTo(ExtractFilePath(ParamStr(0)));
     Close;
   end;
    //удаляем архив который скачали
    DeleteFile(path+'\Update_ARMTitan.zip');
   //перезапуск программы
   fullpath:=path+'\Project2.exe';
   ShellExecute(0, 'open', PWideChar(fullpath), '', nil, SW_SHOW);
   //WinExec(PAnsiChar(fullpath), SW_SHOW); 
   Application.Terminate; // or: Close;
 finally
 end;
end;

Здесь тоже есть недочет, распаковывать лучше в отдельности каждый файл и проверять на наличие ошибки, а не весь архив целиком как сделал я.
Тут есть 2 мелочи которые надо соблюдать: 
1. В директории с программой должен быть файл 7z.dll, поэтому лучше сделать проверку:

if  FileExists(path+'\7z.dll') then 
begin
   ShowMessage('Отсутствует файл 7z.dll');
   exit;
end;

или еще как то по другому.
2. В архиве с обновлением не должен присутствовать файл 7z.dll, так как он используется, или же распаковать всё по отдельности как я писал выше и не распаковывать только этот файл.

Вот и всё. Главное не забыть перед компиляцией готовой программы для обновления прежде чем добавить её в архив, изменить номер версии программы.

В этом способе есть некоторые недочёты и я это знаю. Но пока что я им пользуюсь и проблем не испытывал, хотя доработать всё же следует.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Обсудить материал в конференции Embarcadero »
Написать редактору 
 Рекомендовать » Дата публикации: 09.11.2012 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Enterprise Connectors (1 Year term)
Delphi Professional Named User
CAD Import .NET Professional пользовательская
SmartBear AQtime Pro - Node-Locked License (Includes 1 Year Maintenance)
JIRA Software Commercial (Cloud) Standard 10 Users
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Вопросы и ответы по MS SQL Server
Все о PHP и даже больше
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Слот Биг Бэнг (6)
Большой взрыв как правящая теория сотворения мира. Теперь вы можете поиграть слот Big Bang в...
 
Отличается ли ДрифтКазино от беттинга? (57)
Друзья, давно заметил, что на Дрифте уже несколько месяцев во всю рекламируется и предлагается...
 
Подскажите лучшее онлайн казино (8)
Вот нашёл интересную игровую площадку, и это онлайн казино Вавада. Может кто что подсказать по...
 
Помощь по MS Access (345)
Доброе время суток. Случайно оказался на этом сайте, искал статьи по OLAP. Вижу, что...
 
Требуется Краснодар: Java -разрабочик (2)
Обязанности: Разработка корпоративных backend-приложений для автоматизации розничных продаж...
 
 
 



    
rambler's top100 Rambler's Top100