(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
Delphi Professional Named User
Enterprise Connectors (1 Year term)
Zend Studio Commercial License 1 Year Free Upgrades
DeviceLock Base (базовый компонент) от 1 ПК до 49 ПК
IBM Rational Method Composer Authorized User License
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Delphi - проблемы и решения
Windows и Office: новости и советы
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Рабочее зеркало букмекера 1win (1)
Сегодня в случае недоступно официального сайта есть рабочие зеркала БК 1win...
 
Автомобиль (4)
Доброй ночи. Планируем приобрести авто, рассматриваем б.у варианты, как проще всего подобрать...
 
Новости спорта - все послдение события в одном месте (1)
Пользователи, которые увлекаются ставками на спорт, должно следить за последними изменениями в...
 
Программы Delphi на заказ (241)
Пишу программы в среде Delphi на заказ http://bddelphi.ucoz.ru/
 
Пишу программы на заказ профессионально (3256)
Пишу программы на заказ на языках Pascal (численные методы, списки, деревья, прерывания) под...
 
 
 



    
rambler's top100 Rambler's Top100