Wiele osób ma problemy z napisaniem swojego instalatora, dlatego pokusiłem się o napisanie arta na ten temat. Tekst opisuje mój sposób na stworzenie własnej instalki. Może nie jest najszybszy, ale uwalnia nas od konieczności korzystania z innych aplikacji np. InnoSetup. Każdy będzie mógł również odpowiednio rozbudować swój program dostosowując go do własnych potrzeb (np. dokładając odpowiednią grafikę lub muzykę).
Najpierw musimy napisać program, który spakuje wszystkie pliki naszego programu do jednego archiwum, które zostanie później wykorzystane przez właściwy instalator. Nasza aplikacja znajdzie wszystkie pliki w podanym folderze i wypisze je na komponencie ListBox.
Wstawiamy na formę potrzebne komponenty:
TEdit – name: katalog (pole do wyboru katalogu)
TButton – caption: Przeglądaj
TListBox – name: pliki (nasze pliki) TButton – caption: Buduj
TProgressBar – name: pbar (pasek postępu operacji)
Punktem pierwszym programu będzie napisanie odpowiedniej procedury przeszukującej katalog w poszukiwaniu plików:
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
type TForm1 = class(TForm) private { Private declarations } public procedure SearchFiles(dir:string); end; var Form1: TForm1; implementation procedure TForm1.SearchFiles(dir:string); var sr:tsearchrec; f:integer; begin if (dir[length(dir)]<>'') then dir:=dir+''; // dodajemy na końcu backslash f:=Findfirst(dir+'*.*',faAnyFile,sr); while (f=0) do // dopóki znajduje pliki begin if (sr.Name[1]<>'.') then begin if (sr.Attr and faDirectory)<>faDirectory then // pomiń katalogi pliki.items.add(dir+sr.Name); end; f:=findnext(sr); // znajdź następny plik end; FindClose(sr); // przeszukujemy podkatalogi f:=findfirst(dir+'*.*',faDirectory,sr); while (f=0) do begin if (sr.Name[1]<>'.') then SearchFiles(dir+sr.Name); f:=findnext(sr); end; FindClose(sr); end; |
Podpinamy teraz pod przycisk Przeglądaj procedurę odpowiedzialną za wyświetlenie okna do wyboru katalogu:
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 |
procedure TForm1.Button1Click(Sender: TObject); var s:string; begin // uses FileCtrl SelectDirectory('Wybierz katalog:','My Computer',s); if (s<>'') then // jeżeli wybrano katalog begin katalog.text:=s; pliki.clear; SearchFiles(s); end; end; |
A teraz najważniejsza część, czyli napisanie procedure łączącej pliki. Użyjemy dwóch objektów klasy TFileStream (do odczytu i zapisu). Jak przystało na profesjonaly program, musimy odpowiednio zareagować na występujące wyjątki.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
procedure TForm1.Button2Click(Sender: TObject); const rozmiar_bufora=1024; // rozmiar bufora zapisu/odczytu var buf:array [1..rozmiar_bufora] of char; fin:TFileStream; // plik, z którego czytamy fout:TFileStream; // plik, do którego zapisujemy f_count:dword; // ile plików j,dl,i:dword; ile,reszta:dword; s:string; begin if pliki.Items.count=0 then // jeżeli nie wybrano żadnych plików begin MessageBox(0,'Musisz wybrać pliki!','Uwaga!',MB_OK+MB_ICONSTOP); exit; end; if DirectoryExists(katalog.Text)=false then // jeżeli wybrany katalog nie istnieje begin MessageBox(0,PCHAR('Katalog: '+katalog.text+' nie istnieje!'),'Uwaga!',MB_OK+MB_ICONSTOP); exit; end; try fout:=TFileStream.Create('files.dat',fmCreate or fmOpenWrite); f_count:=pliki.Items.count; pbar.Position:=0; // przygotowujemy progressba pbar.Max:=f_count; fout.Write(f_count,sizeof(f_count)); // zapisujemy ile jest plików for i:=0 to f_count-1 do begin if FileExists(pliki.Items.Strings)=false then begin MessageBox(0,PCHAR('Plik: '+pliki.Items.strings+' nie istnieje!'),'Uwaga!',MB_OK+MB_ICONSTOP); end; fin:=TFileStream.Create(pliki.Items.Strings,fmOpenRead); s:=''; s:=ExtractRelativePath(katalog.Text,pliki.Items.Strings); dl:=length(s); fout.Write(dl,sizeof(dl)); // długo�ć nazwy pliku, wraz z katalogiem for j:=1 to dl do fout.Write(s[j],1); // zapisujemy nazwę pliku dl:=fin.size; fout.Write(dl,sizeof(dl)); // rozmiar pliku ile:=fin.Size div rozmiar_bufora; reszta:=fin.size-(ile*rozmiar_bufora); for j:=1 to ile do begin fin.Read(buf,rozmiar_bufora); fout.Write(buf,rozmiar_bufora); application.ProcessMessages; end; fin.Read(buf,reszta); fout.Write(buf,reszta); application.ProcessMessages; pbar.Position:=pbar.Position+1; fin.Free; end; fout.Free; MessageBox(0,'Plik instalatora zbudowany pomy�lnie!','Uwaga!',MB_OK+MB_ICONINFORMATION); except try fin.Free; except end; try fout.Free; except end; MessageBox(0,'Błšd podczas budowania pliku!','Uwaga!',MB_OK+MB_ICONSTOP); end; end; |
Mamy teraz plik z naszymi danymi. Teraz nie zostało już nic, tylko przejść do drugiej części kursu, w której napiszemy właściwy instalator.
Autor: krajew4