Jak wyświetlić wynik działania aplikacji konsolowej

jas_dream

Artykuł odpowiada na pytanie jak w Delphi uruchomić dany program w trybie konsolowym i wyświetlić jego wynik (np. raport) w komponencie TMemo (oczywiście wynik można odrazu zapisywać, albo np. przedstawić w innym komponencie - wystarczy tylko drobna zmiana kodu)

{ główna funkcja }
function TForm1.RunCaptured(const _dirName, _exeName, _cmdLine, nazwa_pliku: string, tworz_raport: Boolean): Boolean;
var
   start: TStartupInfo;
   procInfo: TProcessInformation;
   tmpName: string; 
   tmp: Windows.THandle; 
   tmpSec: TSecurityAttributes;
   res: TStringList; 
   return: Cardinal; 
begin 
   Result := False; 
   try
{ tmpName to plik w którym zostaną zapisane dane z aplikacji konsolowej }
{ jeżeli wartosc tworz_raport będzie prawdą, jest to także plik tymczasowy }
      tmpName := nazwa_pliku;
      FillChar(tmpSec, SizeOf(tmpSec), #0);
      tmpSec.nLength := SizeOf(tmpSec);
      tmpSec.bInheritHandle := True;
      tmp := Windows.CreateFile(PChar(tmpName),
               Generic_Write, File_Share_Write,
               @tmpSec, Create_Always, File_Attribute_Normal, 0);
      try
         FillChar(start, SizeOf(start), #0);
         start.cb               := SizeOf(start);
         start.hStdOutput   := tmp;
         start.dwFlags      := StartF_UseStdHandles or StartF_UseShowWindow;
         start.wShowWindow := SW_Minimize; 
         { Start programu konsolowego }
         if CreateProcess(nil, PChar(_exeName + ' ' + _cmdLine), nil, nil, True,
                                 0, nil, PChar(_dirName), start, procInfo) then
         begin
            SetPriorityClass(procInfo.hProcess, Idle_Priority_Class);
            WaitForSingleObject(procInfo.hProcess, Infinite);
            GetExitCodeProcess(procInfo.hProcess, return);
            Result := (return = 0);
            CloseHandle(procInfo.hThread);
            CloseHandle(procInfo.hProcess);
            Windows.CloseHandle(tmp);
            { Dodawanie wyniku aplikacji do komoponntu TMemo }
            res := TStringList.Create;
            try
               res.LoadFromFile(tmpName);
               Memo1.Lines.AddStrings(res);
            finally
               res.Free;
            end;
            { jeżeli plik tymczasowy nie potrzebny to go usuń }
            if tworz_raport = false then
            Windows.DeleteFile(PChar(tmpName));
         end
         else
         begin
         { w razie problemów wyswietl komunikat }
            Application.MessageBox(PChar(SysErrorMessage(GetLastError())),
               'Błąd uruchomienia aplikacji konsolowej!', MB_OK);
         end;
      except
         Windows.CloseHandle(tmp);
         { jeżeli plik tymczasowy nie potrzebny to go usuń }
         if tworz_raport = false then
         Windows.DeleteFile(PChar(tmpName));
         raise;
      end;
   finally
   end;
end;


{ przykład }
// C:         -  lokalizacja programu konsolowego w tym przypadku dysk C:
// cmd.exe    -  nazwa programu w tym przypadku cmd.exe
// /c dir     -  parametr dla danego programu
// raport.txt -  nazwa pliku raportującego
// true       -  po zakończeniu nie usuwaj plik raportujący

RunCaptured('C:', 'cmd.exe', '/c dir', 'raport.txt', true);

Info:
http://www.swissdelphicenter.ch/de/showcode.php?id=990

FAQ

11 komentarzy

A co zrobi, żeby to polecenie wykonało się w bierzącej ścierzce, tj.
aby wykonywały się polecenia w typie cd .. itp...

? ?? ? ? ?? ??? ? ?? ?

wro dnia: thx stary właśnie tego potrzebowałem!

Patryk -> a co jeśli program będzie chodził przez 5 sekund? Co się do memo wczyta? :->

byś chociaż napisał kto jest autorem kodu :>

Czasami można prościej:
ShellExecute(Handle, 'open', 'cmd.exe', '/c dir c: > raport.txt', 'C:', SW_HIDE);
Memo1.Lines.LoadFromFile('C:\raport.txt');

jeszcze jest jeden kod: http://www.elists.org/pipermail/delphi/2003-November/024712.html ale niezbyt mi chce chodzic,
jak coś odsyłam, jakbyście mieli jakiekolwiek problemy

dużo łatwiejszym sposobem jest skorzystanie z TDosCommand,

Ale to juz jest w FAQ

to by było na tyle