Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Delphi
Jak spustit program a počkat na jeho ukončení
serial
20. srpna 2001, 00.00 | V dnešním článku se dozvíte, jak z programu v Delphi spustit libovolnou aplikaci a detekovat, kdy je ukončena. Vše je názorně předvedeno na ukázkovém programu.
První část otázky, nadnesené v nadpisu článku, pravděpodobně nebude většině programátorů v Delphi dělat problémy. Pokud chceme z našeho programu spustit jiný program, můžeme použít funkce WinExec nebo ShellExecute, která má lepší možnosti (jejich popis viz nápověda Win32 API). Obě tyto funkce se ale ukončují a vracejí kontrolu na místo volání ihned po spuštění daného programu, a oba programy (původní i spuštěný) pak běží nezávisle. Většinou toto chování vyhovuje, ale někdy je potřeba mít kontrolu nad tím, kdy spouštěný program ukončí svou činnost.
Namátkou mě napadá příklad: Prohlížeč souborů zabalených v archivu. Typicky prohlížený soubor rozbalíme někam do adresáře TEMP a spustíme externí prohlížeč. Bylo by dobré vědět, kdy uživatel tento prohlížeč ukončil, abychom poté mohli smazat soubor z TEMPu a ten nezabíral zbytečně místo na disku. Příkladů na toto téma se určitě najde víc.
Teď se už pojďme podívat, jak požadované chování (čekání na ukončení spuštěného programu) zařídit. Vše si ukážeme na poměrně triviální aplikaci (viz obrázek). Do textového pole uživatel napíše jméno programu, klikne na tlačítko Spustit, zadaný program je spuštěn a pod dobu jeho běhu jsou textové pole i tlačítko "zašedlé". Když se spuštěný program ukončí, oba ovládací prvky se "odšedí" a je možné spustit další program.
Jak na to?Klíčovou funkcí programu je WinExecAndWait. Ta má stejné parametry jako systémová funkce WinExec, ale je vylepšená v tom, že vrací kontrolu až po ukončení spouštěného programu.
K vlastnímu spuštění programu použijeme systémovou funkci CreateProcess. Ta má spoustu parametrů (opět viz Win32 API Help), z nichž většinu ani nevyužijeme. Nejdůležitější jsou příkazová řádka (což je program, který se spustí, i s parametry) a dvě struktury (přesněji ukazatele na ně):
První je typu TStartupInfo a obsahuje spoustu informací, které Windows říkají, jakým způsobem má být daný program spuštěn. Opět většinu z možností nevyužijeme, spokojíme se s nastavením způsobu, jakým se má zobrazit okno aplikace (obdoba druhého parametru systémové funkce WinExec).
Druhá struktura je typu TProcessInformation a nese informace o právě vytvořeném procesu. Není to tedy parametr vstupní, ale výstupní. My z této struktury později využijeme jen handle procesu, který se skrývá pod položkou hProcess.
Funkce CreateProcess vrací ihned po spuštění programu. Na samotné čekání na ukončení použijeme funkci jinou WaitforSingleObject. Tato funkce se využívá především při synchronizaci procesů. Čeká, dokud systémový objekt (který identifikujeme pomocí handle) není v "signalizovaném stavu". Pokud je tímto objektem program, za "signalizovaný stav" se považuje, když je program ukončen. Prvním parametrem této funkce je tedy handle daného objektu a druhým je čas (v milisekundách), jak dlouho chceme čekat na daný objekt. Pokud je tento čas překročen, funkce vrátí hodnotu reprezentovanou konstantou WAIT_TIMEOUT, pokud se do uplynutí daného počtu milisekund program ukončí, funkce vrátí hodnotu WAIT_OBJECT_0. Jako čas je možno zadat i speciální konstantu INFINITE, která čekání prodlužuje do nekonečna.
Funkce WinExecAndWait tedy bude vypadat následovně:
|
A procedura "pověšená" na tlačítko Spustit vypadaá takto:
|
Drobné vylepšení
Pokud byste si takto vytvořený program vyzkoušeli, brzo zjistíte, že během čekání na ukončení spuštěného programu nemůžete v "rodičovské" aplikaci vůbec nic dělat - je prostě zablokovaná. Je to dáno tím, že během volání funkce WaitForSingleObject se nezpracovávají žádné zprávy od Windows, které zajišťují například reakce na vstup od uživatele či překreslování okna.
Řešení je celkem jednoduché - čekání na ukončení spuštěného programu rozdělíme na 100ms úseky. Po každém úseku zjistíme návratovou hodnotu funkce WaitForSingleObject. Pokud nebude WAIT_OBJECT_0, znamená to, že program se ještě neukončil a funkce vrátila kvůli vypršení času. V tom případě zpracujeme hlášení od Windows a spustíme čekání znovu. V případě opačném je spuštěný program zřejmě ukončen a naše funkce může vrátit jeho výstupní kód.
Místo volání funkce WaitForSingleObject tedy kódu umístíme následujících pár řádků:
|
Závěr
Posledním krokem jsme dotáhli náš program do finální podoby, kterou si můžete stáhnout (Delphi 3 a vyšší). I když celý postup vypsaný slovně vypadá poměrně složitě, kód je vcelku jednoduchý a myslím i pochopitelný, a tak vám nic nebrání použít vytvořenou proceduru WinExecAndWait i ve svých programech.
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007