Rozdělení/přesměrování StdOut konzolové aplikace – Delphi – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Rozdělení/přesměrování StdOut konzolové aplikace – Delphi – Fórum – Programujte.comRozdělení/přesměrování StdOut konzolové aplikace – Delphi – Fórum – Programujte.com

 

Sniper
~ Anonymní uživatel
215 příspěvků
22. 2. 2015   #1
-
0
-

Zdravím, můj problém je následující:
Potřebuji nějakým způsobem přesměrovat to, co se zapisuje do konzole pomocí Write(Ln), do souboru (svým způsobem log) ale s tím, že se to bude normálně v té konzoli zobrazovat. Zkrátka se chci napíchnout na StdOut a lít ho do logu aniž bych ho nijak měnil, aneb co je vidět v konzoli aby bylo zapsáno do souboru. Samotné přesměrování do souboru není problém pomocí AssignFile(Output,...), ale pak se (pochopitelně) nic nozobrazí v konzoli.
Zkoušel jsem přesměrovat StdOut na pipe pomocí SetConsoleHandle atd., ale to nefunguje. Takhle to momentálně vypadá: 

unit StdOut2File;

interface

implementation

uses
  Windows;

type
  TThreadParams = record
    Terminated: Integer;
    ReadPipe:   THandle;
    WritePipe:  THandle;
    OldStdOut:  THandle;
    Event:      THandle;
    Thread:     THandle;
    ThreadID:   LongWord;
  end;
  PThreadParams = ^TThreadParams;  

var
  ThreadParams: TThreadParams;

Function ThrProc(Param: PThreadParams): DWORD; stdcall;
const
  BufferSize = 1024;
var
  Buffer:       Pointer;
  BytesRead:    LongWord;
  BytesWritten: LongWord;

  Function Terminated: Boolean;
  begin
    Result := InterlockedExchange(Param^.Terminated,0) <> 0;
  end;

begin
GetMem(Buffer,BufferSize);
try
  while not Terminated do
    begin
      PeekNamedPipe(ThreadParams.ReadPipe,nil,BufferSize,nil,@BytesRead,nil);
      If BytesRead > 0 then
        begin
          ReadFile(ThreadParams.ReadPipe,Buffer^,BufferSize,BytesRead,nil);
          WriteFile(ThreadParams.OldStdOut,Buffer^,BytesRead,BytesWritten,nil);
          //... write buffer to a file
        end
      else WaitForSingleObject(Param^.Event,100);
    end;
finally
  FreeMem(Buffer,BufferSize);
end;
Result := 0;
end;

procedure Initialize;
begin
InterlockedExchange(ThreadParams.Terminated,0);
CreatePipe(ThreadParams.ReadPipe,ThreadParams.WritePipe,nil,0);
ThreadParams.OldStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
SetStdHandle(STD_OUTPUT_HANDLE,ThreadParams.WritePipe);
ThreadParams.Event := CreateEvent(nil,False,False,nil);
ThreadParams.Thread := CreateThread(nil,0,@ThrProc,@ThreadParams,0,ThreadParams.ThreadID);
end;

procedure Finalize;
begin
InterlockedExchange(ThreadParams.Terminated,1);
SetEvent(ThreadParams.Event);
WaitForSingleObject(ThreadParams.Thread,INFINITE);
SetStdHandle(STD_OUTPUT_HANDLE,ThreadParams.OldStdOut);
CloseHandle(ThreadParams.ReadPipe);
CloseHandle(ThreadParams.WritePipe);
CloseHandle(ThreadParams.Thread);
CloseHandle(ThreadParams.Event);
end;

initialization
  Initialize;

finalization
  Finalize;

end.
var
  TestStr:  String = 'Hello World!' + sLineBreak;
  OutBytes: LongWord;

begin
  WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),PChar(TestStr)^,Length(TestStr) * SizeOf(Char),OutBytes,nil);   // funguje, v pipe je text
  WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),PChar(TestStr),Length(TestStr) * SizeOf(Char),OutBytes,nil); // nefunguje, pipe je prázdná (zřejmě kvůli jinému handle, očekává console screen buffer)
  WriteLn(TestStr);                                                                                         // nefunguje, pipe je prázdná
  ReadLn;
end.

Poradí mi někdo kde dělám nesmysly, případně jak to udělat jinak (a ideálně funkčně ;D )?
Je to v Delphi 7 Personal.
Předem díky.

Nahlásit jako SPAM
IP: 90.179.201.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 7 hostů

Podobná vlákna

Konzolové aplikace — založil fatbooy

Sys.stdout.flush() — založil Tom@sQo

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý