В этой статье расскажу, как в своих программах сделать проверку обновлений и автоматическое обновление.
Что для этого потребуется: php-скрипт, которому посылается текущая версия и в зависимости от присланной версии он будет выдавать: 0 или 1 (или прямую ссылку на новую версию программы); ну и сервер, на который загружать новые версии программ (-ы), чтобы скачивать ее можно было бы по прямой ссылке, а не после ввода 20 капч 🙂
Приступим. PHP-скрипт будет иметь такой вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php $current_version=100.00; if ($_GET['version']<$current_version) { print("1"); } else { print("0"); } ?> |
Как видно, скрипту мы гетом передаем текущую версию, точнее не мы, а программа, в которую это значение «вшито».
Теперь нам нужна программа-апдейтер, которая будет проверять обновления и если есть новая версия — закрывать нашу программу, скачивать новую версию и снова запускать программу.
Функции, которые нам пригодятся:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
uses URLMon; ... function KillTask(ExeFileName: string): integer; const PROCESS_TERMINATE=$0001; var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin result := 0; FSnapshotHandle := CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := Sizeof(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32); while integer(ContinueLoop)<> 0 do begin if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then Result := Integer(TerminateProcess(OpenProcess( PROCESS_TERMINATE, BOOL(0), FProcessEntry32.th32ProcessID), 0)); ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);end; CloseHandle(FSnapshotHandle); end; function DownloadFile(SourceFile, DestFile: string): Boolean; begin try Result:=UrlDownloadToFile(nil,PChar(SourceFile),PChar(DestFile),0,nil)=0; except Result := False; end; end; |
Первая функция убивает процесс, вторая — скачивает файл по указанной ссылке и сохраняет его по указанному пути.
Перейдем к самой проверки обновлений.
Программу-апдейтер можете оформлять, как душе угодно 🙂 Код, который будет ниже, можете совать куда хотите: в таймер, в OnShow формы и т.п.
Кидаем на форму IdHTTP. И в OnShow формы добавляем:
1 2 3 4 5 |
if Pos('/u',ParamStr(1))=0 then begin Form1.Close; end else version:=Copy(ParamStr(1),3,Length(ParamStr(1))); |
, т.е. если отсутствует параметр «/u» — мы закрывает программу-апдейтер, если есть — копируем версию (основная программа будет запускать апдейтер с параметром /u<версия_программы>).
Далее сам код проверки обновлений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var ResMemo: TMemo; //создаем мемо, куда будем грузить результат (можно и TStringList) begin ResMemo:=TMemo.Create(Form1); ResMemo.Parent:=Form1; ResMemo.Visible:=false; ResMemo.ScrollBars:=ssBoth; try ResMemo.Lines.Append(IDHttp1.Get('http://www.softez.pp.ua/upd.php?version=' +version)); //загружаем наш скрипт except ResMemo.Lines.Strings[0]:='0'; //если нет доступа к скрипту, то новых версий нет end; if ResMemo.Lines.Strings[0]='1' then //если есть новая версия - загружаем begin KillTask('Prog.exe'); //убиваем процесс нашей программы DownLoadFile('http://softez.pp.ua/Prog.exe', ExtractFilePath(Application.Exename) +'Prog.exe'); // загружаем новую версию программы и сохраняем ее в папку с апдейтером (а апдейтер находится в папке с программой) ShellExecute(Handle, 'open', PChar(((ExtractFilePath(Application.Exename) +'Prog.exe'))), nil, nil, SW_SHOWNORMAL); //открываем программу Form1.Close; end else begin Form1.Close; //если обновлений нет - закрываем апдейтер end; |
На этом написание апдейтера завершено. Теперь напишем функцию в основной программе, которая будет запускать апдейтер и ждать, пока он завершится (или пока программу не убьет сам апдейтер :)).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
version:='100.00'; //текущая версия программы FillChar(exInfo, SizeOf(exInfo), 0); with exInfo do begin cbSize := SizeOf(exInfo); fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT; Wnd := GetActiveWindow(); ExInfo.lpVerb := 'open'; lpFile := PChar(ExtractFilePath(Application.Exename) +'Updater.exe'); lpDirectory:=PChar(ExtractFilePath(Application.Exename)); lpParameters:=PChar('/u' +version); nShow := SW_Minimize; end; if ShellExecuteEx(@exInfo) then //запускаем апдейтер с инфой, что указали выше begin Ph := exInfo.HProcess; end else Exit; while WaitForSingleObject(ExInfo.hProcess, 50) <> WAIT_OBJECT_0 do //ждем, пока завершится апдейтер Application.ProcessMessages; CloseHandle(Ph); |
Ну, как-то так. На этом — всё 🙂
Выдает ошибки
Мои соболезнования.