Opi, Szczawik fajne opcje. Program póki co pozwala na wiele instancji ale to nie problem z dokodowaniem mutexa i odpalenie skryptu. Szczawik, Twój pomysł brzmi apetycznie zobaczę jak z kodowaniem tego. Jak polegnę to pójdzie opcja Opi. Dzięki za pomoc. Jak się uda to dokleję kod robiący to coś.
PTwr projekt zbyt zaawansowany abym się chciał pokusić na taką modyfikację struktury kodu.
Poszło:
1). Do głównej aplikacji dodałem opcje odpalania się tylko w 1 instancji. Stary dobry mutex
// plik *.dpr
CreateMutex(nil, false, PChar('{MUTEX FIRE SHEET GUID}'));
if GetLastError() = 0 then
begin
Application.Initialize;
Application.CreateForm(TDM, DM);
(...)
Application.CreateForm(TDownloadForm, DownloadForm);
Application.Run;
end;
-
Stworzyłem aplikację czekającą na zamknięcie aplikacji głównej. Timer sprawdza co 1s czy aplikacja się zakończyła. Sprawdzanie za pomocą FindWindow()
-
Aplikacja główna odpala programik do kopiowania pliku ze źródła do celu. Program dostaje dwa parametry. Ważne aby użyć do ich przekazania krótkich nazw plików (wersja 8.3). Jeżeli ścieżka ma spacje to delphi rozbije to na kolejne parametry
// rozpoczecie aktualizacji
procedure TMainForm.btDownloadClick(Sender: TObject);
begin
if DownloadForm.ShowModal() = mrOk then
begin
// aktualną wersję trzymam sobie w pliku *.ini. Rozwiązanie nie ważne - działa ;-)
Config.Ini.WriteInteger('VERSION', 'MajorVersion', Major);
Config.Ini.WriteInteger('VERSION', 'MinorVersion', Minor);
// Tu mi sporo zeszło właśnie na te nazwy plików. Jak podałem ścieżki dostępowe to miałem
// ParamCount = 7 zamiast 2
// Odpala aktualizator - on czeka na zamknięcie głównej aplikacji
ShellExecute(0, nil, 'Download.exe', PChar(Format('%s %s',
[ExtractShortPathName(Config.cDownload.DowloadPath)+DownloadFile,
ExtractShortPathName(ExtractFilePath(Application.ExeName))+'FireSheet.exe'])),
'', SW_SHOWNORMAL);
// Kończenie
Application.Terminate();
end;
end;
- Kod aktualizatora
procedure TDownloadForm.TimerTimer(Sender: TObject);
var
i :Integer;
begin
// co 1s sprawdza istnienie okna
h_wnd := FindWindow('TMainForm', 'MainForm');
// jeżeli go nie ma to znaczy, że aplikacja zamknieta
if h_wnd = 0 then
begin
Timer.Enabled := false;
// mały wodotrysk dla usera ;-)
for i := 0 to pbCopyFile.Max do
begin
pbCopyFile.Position := i;
Sleep(20);
end;
try
// podmianka plików
CopyFile(PChar(ParamStr(1)), PChar(ParamStr(2)), false);
except
ShowMessage('Aktualizacja nie powodla się');
end;
// Ponowne odpalenie głównej aplikacji
ShellExecute(DownloadForm.Handle, nil, 'FireSheet.exe', '', '', SW_SHOWNORMAL);
// Zamknięcie aktualizatora
Application.Terminate();
end;
end;
- Fragment pliku *.ini
[DOWNLOAD]
DownloadPath="D:\"
[VERSION]
MajorVersion=3
MinorVersion=7
- Jak aplikacja główna sprawdza czy są aktualizacje:
procedure TMainForm.TimerTimer(Sender: TObject);
var
sRec :TSearchRec;
begin
// w folderze zawsze będzie jeden plik *.exe o budowie XXYY.exe gdzie XX to major a YY to minor
// 0307.exe
// oraz plik info.txt aby user widział co było dodane
if FindFirst(Config.cDownload.DowloadPath+'*.exe', faAnyFile, sRec) = 0 then
begin
DownloadFile := sRec.Name;
// pobranie wersji do porównania
Major := StrToIntDef(Copy(DownloadFile, 1, 2), 3);
Minor := StrToIntDef(Copy(DownLoadFile, 3, 2), 0);
// jeżeli aktualizacja jest nowsza niż obecny plik
if Major >= Config.cVersion.Major then
begin
if Minor > Config.cVersion.Minor then
begin
btDownload.Visible := true;
end;
end else
end else
begin
btDownload.Visible := false;
end;
FindClose(sRec);
end;
Dzięki chłopaki za podsunięcie rozwiązania. Właśnie dlatego uwielbiam to forum :-) . Zawsze można liczyć na ciekawe pomysły. Bardzo fajnie powstają tutaj burze mózgów.