Programowanie w języku Delphi » Gotowce

Update programu

  • 2007-11-15 15:25
  • 30 komentarzy
  • 2488 odsłon
  • Oceń ten tekst jako pierwszy
Fajnie byłoby, aby program miał możliwość sprawdzenia, czy wyszła jego nowsza wersja. Zaprezentuję tutaj prosty sposób wg mojego pomysłu.

Potrzebne będą nam: konto na jakimś serwerze i komponent HTTPGet. Nie wiem, czy jest on na tej stronie, ale zamieszczam go do przykładowego programu, który znajdziecie w kodach źródłowych.

No więc zaczynamy.
Na początek stwórz plik version.ini. Potrzebny będzie, aby odczytać, czy wyszła nowa wersja programu. Plik będzie wyglądał tak:

[update]
version=1.3
url=http://www.web-page.pl/program.exe

Oczywiście url trzeba dostosować do swojej strony www.
Teraz przechodzimy do Delphi. Wrzuć na formę komponenty: Memo, Button, 2 HTTPGet i ProgressBar.
Wersję można wyciągnąć z zasobów, ale ja zadeklaruję tylko stałą:

const
  wersja = '1.2';


W zdarzeniu OnClick przycisku wpisz:

procedure TForm1.Button1Click(Sender: TObject);
begin
 HTTPGet1.URL := 'http://www.web-page.pl/version.ini';  //lokalizacja pliku z informacją
 HTTPGet1.FileName := ExtractFilePath(Application.ExeName) + 'version.ini'; 
 HTTPGet1.GetFile;  //pobranie pliku ini
 Memo1.Lines.Add('Pobieranie informacji...'); 
end;


Teraz w zdarzeniu onDoneFile komponentu HttpGet1 wpisz:

procedure TForm1.HTTPGet1DoneFile(Sender: TObject; FileName: String;
  FileSize: Integer);
var
 INI : TINIFile;
 updtVersion : string;
 cyfra1 : integer;
 cyfra2 : integer;
 updtCyfr1 : integer;
 updtCyfr2 : integer;
begin
 Memo1.Lines.Add('Sprawdzanie, czy jest nowa wersja');
 INI := TINIFile.Create(HTTPGet1.FileName);
 try
   updtVersion := INI.ReadString('update','version','');  //odcytanie wersji z pliku ini
 
   //nie śmiejcie sie z tego sposobu. To tylko przykład :)
   cyfra1 := StrToInt(wersja[1]);
   cyfra2 := StrToInt(wersja[3]);
   updtCyfr1 := StrToInt(updtVersion[1]);
   updtCyfr2 := StrToInt(updtVersion[3]);
   if (cyfra1 < updtCyfr1) or (cyfra2 < updtCyfr2) then  //sprawdzenie, czy jest nowa wersja
   begin
     Memo1.Lines.Add('Jest nowa wersja programu');
 
{wyświetlenie zapytania. Jeśli użytkownik wybierze Tak, rozpoczyna się pobieranie programu }
     if Application.MessageBox('Czy chcesz pobrać nową wersję programu?','Informacja',MB_YesNo) =
      ID_NO then
      exit
     else
      begin
       HTTPGet2.URL := INI.ReadString('update','url','');
       if SaveDialog1.Execute then  // tu użytkownik wybierze, gdzie zapisać program
         HTTPGet2.FileName := SaveDialog1.FileName;  
       HTTPGet2.GetFile;  //pobieranie pliku
       Memo1.Lines.Add('Pobieranie pliku');
      end;
   end
   else
      Memo1.Lines.Add('Nie znaleziono nowej wersji prormu');
 finally
   INI.Free;
   DeleteFile(HTTPGet1.FileName); //usunięcie pliku ini
 end;
 
end;


Następnie w OnError komponentu HttpGet1:

procedure TForm1.HTTPGet1Error(Sender: TObject);
begin
 Memo1.Lines.Add('Wystąpił błąd');
end;


Następnie w OnDoneFile komponentu HttpGet2:

procedure TForm1.HTTPGet2DoneFile(Sender: TObject; FileName: String;
  FileSize: Integer);
begin
 Memo1.Lines.Add('Pobieranie zakończone sukcesem');
end;


Teraz w OnError HttpGet2:

procedure TForm1.HTTPGet2Error(Sender: TObject);
begin
  Memo1.Lines.Add('Wystąpił błąd podczas pobierania pliku');
end;


No i na koniec w onProgress komponentu HttpGet2:

procedure TForm1.HTTPGet2Progress(Sender: TObject; TotalSize,
  Readed: Integer);
begin
  ProgressBar1.Max := TotalSize;
  ProgressBar1.Position := Readed;
end;


Teraz wystarczy tylko wrzucić plik version.ini na serwer.
To był oczywiście najprostszy sposób na uaktualnienie swojego programu, ale wystarczy troszkę wyobraźni i
rozbudowanie tego kodu nie będzie problemem.

pozdrawiam:
Piotrek Chmolowski

Kod przykładowego programu możecie pobrać tutaj:

http://4programmers.net/download.html?id=1036

30 komentarzy

kuty 2013-01-11 21:41

Zapraszam na moją stronę www.programistakuty.pl. Tam prezentuje mój darmowy program (bardzo łatwo konfigurowalny) do aktualizacji programu. Prezentuje tam wykorzystanie go w delphi oraz dołączam przykładowy projekt. Strona artykułu http://programistakuty.pl/kuty-updater/

BoZzDoG 2011-08-07 11:50

Wklejam kod funkcji, która sprawdza czy jest nowa wersja programu bazując na dwóch plikach:

function TMainForm.IsNewVesrion(const VersionFileName, UpdateFileName: ShortString): Boolean;
var
  {ZMIENNE PLIKOWE}
  iniVersion, iniUpdate: TINIFile;
  {ZMIENNA LICZNIKOWA}
  I: Byte;
begin
  {DOMYŚLNY REZULTAT FUNKCJI}
  Result := False;

  try
    {TWORZENIE ZMIENNYCH PLIKOWYCH}
    iniVersion := TINIFile.Create(VersionFileName);
    iniUpdate := TINIFile.Create(UpdateFileName);

    {SPRAWDZANIE POSZCZEGÓLNYCH LICZB WERSJI}
    for I := 0 to 3 do
      if iniUpdate.ReadInteger('CURRENT_VERSION', IntToStr(I), 0) > iniVersion.ReadInteger('CURRENT_VERSION', IntToStr(I), 0) then
        begin
          {JEŚLI JEST WYŻSZA LICZBA WERSJI ZWRÓĆ TRUE}
          Result := True;
          Break;
        end;
  finally
   {USUŃ ZMIENNE PLIKOWE Z PAMIĘCI}
    FreeAndNil(iniVersion);
    FreeAndNil(iniUpdate);
  end;
end;

Budowa plików jest prosta. Oto plik Version.ini - są w nim informacje na temat aktualnie posiadanej wersji programu:

[CURRENT_VERSION]
0=1
1=0
2=0
3=154

A to zawartość pliku Update.ini - jest to plik pobrany z sieci przechowujący informacje na temat najnowszej wersji programu:

[CURRENT_VERSION]
0=1
1=0
2=0
3=157

Jak widać jest w nim młodsza wersja programu, stąd funkcja zwróci prawdę. Algorytm nie myli się i nalezy go używać tuż po pobraniu pliku wersji z Internetu. Pozdrawiam.

BoZzDoG 2011-08-07 10:59

BTW: A poza tym algorytm nie jest w pełni poprawny, by jeżeli wersja aplikacji wzrośnie do 10, program odczyta go jako 1...

Metoda z liczbami jest uniwersalna, na łańcuchach niestety nie...

BoZzDoG 2011-08-07 10:57

Witajcie. Dlaczego wersję programu odczytujecie jako łańcuch? Przecież klasa TINIFile posiada możliwość odczytywania zawartości kluczy jako liczb metodą INI.ReadInteger... Zamiast kombinować z konwertowaniem tekstu na liczby wystarczy podzielić numer wersji na bloki i je porównywać (zawartość pliku version.ini):

[CURRENT_VERSION]
Major=1
Minor=0
Release=0
Build=2043

Teraz pobrać do odpowiednich zmiennych te liczby i porównać. Można by było zapisać je do tablicy i jedną pętlą sprawdzić czy wersja aplikacji w pliku version.ini jest nowsza niż tej na dysku. No ale trzeba by było trochę pogłówkować =)

pawel8115 2010-07-11 16:14

Czy mógł by ktoś zamieścić kod żródłowy tego programu , ponieważ niewiem dlaczego ale wywala mi błąd podczas kliknięcia na button .
bład jest w tej linijce :

   updtCyfr1 := StrToInt(updtVersion[1]);
 
kod programu :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IniFiles, XPMan, ComCtrls, StdCtrls, HTTPGet;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    XPManifest1: TXPManifest;
    SaveDialog1: TSaveDialog;
    HTTPGet1: THTTPGet;
    HTTPGet2: THTTPGet;
    procedure Button1Click(Sender: TObject);
    procedure HTTPGet1DoneFile(Sender: TObject; FileName: String;
      FileSize: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  wersja = '1.2';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 HTTPGet1.URL := 'http://www.pm2a.yoyo.pl/updater/version.ini';  //lokalizacja pliku z informacją
 HTTPGet1.FileName := ExtractFilePath(Application.ExeName) + 'version.ini';
 HTTPGet1.GetFile;  //pobranie pliku ini
 Memo1.Lines.Add('Pobieranie informacji...');
end;

procedure TForm1.HTTPGet1DoneFile(Sender: TObject; FileName: String;
  FileSize: Integer);

  var
 INI : TINIFile;
 updtVersion : string;
 cyfra1 : integer;
 cyfra2 : integer;
 updtCyfr1 : integer;
 updtCyfr2 : integer;
begin
 Memo1.Lines.Add('Sprawdzanie, czy jest nowa wersja');
 INI := TINIFile.Create(HTTPGet1.FileName);
 try
   updtVersion := INI.ReadString('update','version',);  //odcytanie wersji z pliku ini

   //nie śmiejcie sie z tego sposobu. To tylko przykład :)
   cyfra1 := StrToInt(wersja[1]);
   cyfra2 := StrToInt(wersja[3]);
   updtCyfr1 := StrToInt(updtVersion[1]);
   updtCyfr2 := StrToInt(updtVersion[3]);
   if (cyfra1 < updtCyfr1) or (cyfra2 < updtCyfr2) then  //sprawdzenie, czy jest nowa wersja
   begin
     Memo1.Lines.Add('Jest nowa wersja programu');

{wyświetlenie zapytania. Jeśli użytkownik wybierze Tak, rozpoczyna się pobieranie programu }
     if Application.MessageBox('Czy chcesz pobrać nową wersję programu?','Informacja',MB_YesNo) =
      ID_NO then
      exit
     else
      begin
       HTTPGet2.URL := INI.ReadString('update','url',
);
       if SaveDialog1.Execute then  // tu użytkownik wybierze, gdzie zapisać program
         HTTPGet2.FileName := SaveDialog1.FileName;
       HTTPGet2.GetFile;  //pobieranie pliku
       Memo1.Lines.Add('Pobieranie pliku');
      end;
   end
   else
      Memo1.Lines.Add('Nie znaleziono nowej wersji prormu');
 finally
   INI.Free;
   DeleteFile(HTTPGet1.FileName); //usunięcie pliku ini
 end;
end;

end.

Co w nim jest nie tak ??

siekierzyński 2009-11-14 23:26

Kodzik ciekawy, mi się przyda niedługo :)

maxi 2008-06-08 16:20

na yoyo żeby ściągać plik przez HTTP nigdzie się nie musisz logować, nie wiem skąd to wziąłeś

nav, pisałem o tym trochę niżej...

rysio93 2008-02-07 16:59

a znacie może jakaś dobra stronkę gdzie by założyć konto ?? bo na yoyo trzeba sie zalogować żeby ściągnąć plik na cba.pl i republice tez :(((

sitcome 2009-12-23 22:09

Zawsze można zrobić tak że na serwerze jest plik np. nazwa_numer.wersji i przy odpalaniu program próbuje pobrać ten plik jeśli go nie ma na serwerze,  to nie ma aktualizacji wydaje mi się za bardzo prymitywna wersja jest chyba najlepsza :]

siwy16l 2007-09-13 14:05

a mi w tym miejscu kodu podkreśla błąd... o co chodzi??
INI : TINIFile;

Undeclared identifer: 'TINIfile'

używam delphi 7 personal

siwy16l 2007-09-13 21:08

uprałem sie z problemem xD jak ktoś nie wie to do uses trzeba dopisać IniFiles

bordeux 2007-05-16 17:33

Teraz juz wiem..... moglem najpierw pomyslec, a pozniej dodac komentarz :)

maxi 2007-04-11 19:41

bordeux, nie dodałeś komponentu SaveDialog na formatkę.

Mam jedną uwagę dot. linijki 21 z procedury TForm1.HTTPGet1DoneFile. Tam jest:

if (cyfra1 < updtCyfr1) or (cyfra2 < updtCyfr2) then ...

ale jeśli program będzie np. w wersji 2.1 a ktoś nieszczęśliwie zapomni zaktualizować pliku na serwerze i tam będzie podane 1.9 to zacznie się nie upgrade, tylko DOWNGRADE (bo w tym wypadku cyfra2 > updtCyfr2)! To jest sytuacja wyjątkowa spowodowana przez osobę opiekującą się serwerem, ale pamięć ludzka jest zawodna więc proponuję takie coś:

if (cyfra1 < updtCyfr1) or ((cyfra1 = updtCyfr1) and (cyfra2 < updtCyfr2)) then ...

chyba będzie działać, ale nie jestem pewny bo dopiero zaczynam przygodę z Delphi

bordeux 2007-03-18 12:10

A mi wyskakuje bląd cos SaveDialog1 undeclared? co to znaczy??

sochalewski 2007-02-23 16:29

wyskakuje blad httpget, bo nie masz tego komponentu zainstalowanego [ot, caly problem]

Armi 2006-03-31 16:29

Mam mały problem w use występuje mi błąd   [Fatal Error] Unit1.pas(7): File not found: 'HTTPGet.dcu' i zaznacza mi się HTTPGet prosze poradzcie mi co mam z tym zrobić [???]

Thomashek 2005-01-02 19:11

Wpisz INIFiles do uses

JarekM 2004-12-05 20:57

Ja mam problem...[Error] Unit2.pas(53): Undeclared identifier: 'TINIFile'

Wiecie dlaczego?

migajek 2004-11-28 12:32

Swoją drogą, co wy tak macie z tym HTTPGet ? ;) Ja tam wolę stare dobre UrlDownloadToFile, bo mozna go zastosować wszędzie, również programując w API. I dzięki temu mój programik Downloader nie musi mieć formy w dfm ani classes w uses :P

kubARek 2004-04-04 13:17

dzieki. moze sie przydac :)
a wiecie ze ja znalazlem gdzies w sieci opis uzycia OpenDialog. Slowko w slowko to samo ;) Musieli zerznac z ksiazki Adama B. ;)

czarownik 2004-02-02 12:36

prawie to samo jest w kompendium programisty d7 Adama... ;]

piwko28 2004-01-06 20:07

Zgadzam sie z Wolverinem, na taki sam pomysl wpadlem podczas pisania swojego programu. Bo najlatwiej go zrealizowac :P

Dobre do czasu, do kiedy nie usuna Ci konta (na bezplatnym serwerze) :D

Wolverine 2003-12-30 14:04

hej nie bulwersuj sie, na taka metode wpada sie po 5 sekundach myslenia o update'ach programu. Poza tym nawet ja nie pisze "sluwko"

Adam's 2003-10-05 14:30

zerżnołeś albo ktoś zerżną z ciebie słuwko w słuwko znalazłem to na koder.prv.pl
// o mamo, ale byki... - ŁF

lofix 2003-07-15 12:50

ja nie mowie ze zerznales..mowie tylko ze kod adama to 1/3 tego

Krzemin 2003-07-10 12:19

Nawet niezłe, ale powien Ci co ja zrobiłem : na serwerku walnąłem plik textowy w takim formacie :

NAZWAPLIKU;URL_DO_NIEGO

W ten sposób można zamieścić nie tylko jedną wersję, ale np. uaktualnienia do bibliotek (jeśli ich używamy), starsze wersje programu itp...

chmolu 2003-07-10 16:15

Przecież mój sposób bardzo łatwo rozbudować.
Wystarczy jakiś pomysł. Można np. dać drugi link do pliku z informacją co nowego w programie.

chmolu 2003-07-12 11:14

zapewniam Cię, lofix, że tej książki nie widziałem na oczy.

lofix 2003-07-12 09:43

TO samo (tzn podobny sposob, tyle ze prostszy) znajduje sie w ksiazce Adama (D7cwzaw) ciekawe.. :/

nav 2007-11-15 21:48

Taki drobny problem - 1.9 będzie nowsza niż 2.1 :-) Lepiej skonwertować na floata.