Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Warten bis ein Process wieder ready ist (https://www.delphipraxis.net/101233-warten-bis-ein-process-wieder-ready-ist.html)

gibb 10. Okt 2007 09:47


Warten bis ein Process wieder ready ist
 
Hallo miteinander

Ich bin auf der suche nach einer möglichkeit zu prüffen ob meine cmd process immernoch arbeitet oder nicht.


Wundert euch nicht über sonderheitem im Code, ich hatte bisher das so realisiert das man beim aufruf ein Endzeichen mitgeben kann sowie ein timer, Es war bisher so das ich gewartet habe bis entweder das zeichen kommt oder der Timer ableuft und dann das nächste comando der konsole übergeben habe. nun waitforsingleObject wartet bis der process beendet wird, aber ich will ihn ja garnicht beenden sondern ein weiteres commando später absetzen. also wirklich so arbeiten wie die Konsole...

Die version hier funktioniert gut solange man in etwa abschätzen kann wielange der computer braucht um den befehl auszuführen sowie man einen rückgabewert hat. Mein problem ist nun das ich keinen output kriege und nicht weis wielange er braucht bis er fertig ist aber dennoch bemerken muss wann er fertig ist. wisst ihr also wie ich den process fragen kann ob er noch beschäftigt ist oder nicht ?

bin wirklich kurz vor dem verzweifeln..

danke schonmal im voraus und liebe grüsse

Severin


Delphi-Quellcode:
procedure TConsoleThread.RC_Run(Command: string);
const bufsize=1024; // 1KByte buffer
var
  buf: array [0..bufsize-1] of char;
  si: tSTARTUPINFO;
  sa: tSECURITYATTRIBUTES;
//  sd: tSECURITYDESCRIPTOR;
  pi: tPROCESSINFORMATION;
  newstdin, newstdout, read_stdout, write_stdin: tHandle;
  bread, avail: dword;
  OffTime : Integer;
  ConsoleCommand, StringOffTime: string;
  CommandTypePos,OffCharPos : Integer;

begin

    //Initialisierung ProcessInfo
  FillChar(pi, SizeOf(TProcessInformation), 0);

    //Initialisierung SecurityAttr
  FillChar(sa, SizeOf(TSecurityAttributes), 0);
  sa.nLength := SizeOf(sa);
  sa.bInheritHandle := true;
  sa.lpSecurityDescriptor := nil;

    // create pipe A
  if not CreatePipe(newstdin, write_stdin, @sa, 0) then
  begin
      TriggerConsoleOut('Error creating Pipe A');
      exit;
  end;
    // create Pipe B
  if not CreatePipe(read_stdout, newstdout, @sa, 0) then begin
    TriggerConsoleOut('Error creating Pipe B');
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    exit;
  end;
    // Conf. si
  GetStartupInfo(si);
  si.dwFlags:=STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  si.wShowWindow:=SW_HIDE;
  si.hStdOutput:=newstdout;
  si.hStdError:=newstdout;
  si.hStdInput:=newstdin;
    // Create Process
  if not CreateProcess(pchar(command), pchar('/a'), nil, nil, true,
    CREATE_NEW_CONSOLE, nil, nil, si, pi) then
  begin
    TriggerConsoleOut('Error creating process: '+command);
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    exit;
  end;
    // Loop principal
  fillchar(buf, sizeof(buf), 0);
  FRC_End:=false;
//  FRC_SendBuf:='';
  repeat

    if FInQueue.count > 0 then
    begin
      if Length(FRC_SendBuf) = 0 then
      begin
        waitforsingleobject(pi.hProcess,100); //<----- hier müsste man warten bis die Konsole ready ist hier wäre //sonst eine boolean variable die auf true geht sobald der timer ableuft oder das endzeichen kommt.
          if pos('#',FInQueue[0])<> 0 then            
          begin                                      
            CommandTypePos := pos('#1',FInQueue[0]);
            OffCharPos := pos('#2',FInQueue[0]);

            OffTime:= 20000;
            FCommandType:= copy(FInQueue[0],CommandTypePos+2,OffCharPos - (CommandTypePos + 2));
            FOffChar:=copy(FInQueue[0],OffCharPos+2,(length(FInQueue[0])+1)-(OffCharPos+2));
            ConsoleCommand := copy(FInQueue[0],1,(CommandTypePos-1));
            FTimer.Interval := OffTime;
            FTimer.Enabled:= true;
            FRC_SendBuf := '';
            FRC_SendBuf := ConsoleCommand+ CRLF;//FInQueue[0];
            FInQueue.Delete(0);
            modlogger.AddToLog('der Console Kommando Queue wurde folgendes kommando zur verarbeitung hinausgenommen.' +
                             FRC_SendBuf, ModDebug);
            FReady:= False;
          end
          else
          begin
            FOffChar := '';
            FTimer.Interval := 20000;
            FTimer.Enabled:= true;
            FRC_SendBuf := '';
            FRC_SendBuf :=FInQueue[0]+ CRLF;
            FInQueue.count;
            FInQueue.Delete(0);
            FReady:= False;
          end;
      end;
    end;
    OffTime := OffTime;
    application.processmessages;
  //    Application.HandleMessage;
    GetExitCodeProcess(pi.hProcess, FRC_ExitCode);
    if (FRC_ExitCode <> STILL_ACTIVE) then FRC_End:=True;
    PeekNamedPipe(read_stdout, @buf, bufsize, @bread, @avail, nil);
      // Comprobamos texto de salida
    if (bread<>0) then begin
      fillchar(buf, bufsize, 0);
      if (avail > bufsize) then
        while (bread >= bufsize) do begin
          ReadFile(read_stdout, buf, bufsize, bread, nil);
          SplitLines(buf);
          fillchar(buf, bufsize, 0);
        end
      else begin
        ReadFile(read_stdout, buf, bufsize, bread, nil);
        SplitLines(buf);
      end;
    end;
      // Eingabe text
   while (Length(FRC_SendBuf) > 0) do
   begin    
     WriteFile(write_stdin, FRC_SendBuf[1], 1, bread, nil);
     Delete(FRC_SendBuf, 1, 1);
   end;
  until FRC_End or Terminated;
    // Close
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
  Terminate;
end;

Dezipaitor 10. Okt 2007 10:39

Re: Warten bis ein Process wieder ready ist
 
Ich hab mal gelesen, dass man WM_NULL mit SendMessageTimeOut verwenden kann.
WM_NULL macht einfach nix, und SendMessageTimeOut wartet solange bis die Nachricht verarbeitet wurde oder es ein Timeout gibt.
Das garantiert aber nicht, dass der Prozess wirklich abgestürzt ist.

Entweder ist der Prozess wirklich zu stark beschäftigt und es dauert einfach eine Weile, der Prozess wartet auf eine Funktion, die auf einen HW-I/O-Funktion wartet oder es gab eine AV und eine Dialogbox von Windows wird angezeigt.

gibb 10. Okt 2007 10:49

Re: Warten bis ein Process wieder ready ist
 
Entschuldige aber ich habe das gerade nicht verstanden :-/

wie soll mir das helfen festzustellen wann der Prozess wieder bereit für neues ist ?

lg Severin

Dezipaitor 10. Okt 2007 11:03

Re: Warten bis ein Process wieder ready ist
 
Hmm, sorry, ich hab übersehen, dass es wohl nicht für Konsole funktioniert.

gibb 10. Okt 2007 12:39

Re: Warten bis ein Process wieder ready ist
 
Naja keine ursache... schade aber vieleicht hat ja sonst jemand einen vorschlag...

lg sev

gibb 11. Okt 2007 07:40

Re: Warten bis ein Process wieder ready ist
 
Hallo,

Ich hatte ne idee aber ich weiss nicht ob sie umsetzbar ist. Angenommen ich würde irgendwie die änderung der speicherbenutzung abfragen (unter dem taskmanager bei den Prozessen zu finden wenn man die ansicht anpasst.) könnte ich ja theoretisch schauen wann diese sich über längere zeit nicht mehr verändert und dann davon ausgehen das mein process nicht mehr in arbeit ist. würde das gehen ?

lg sev

wäre wirklich über ideen froh.

OregonGhost 11. Okt 2007 09:47

Re: Warten bis ein Process wieder ready ist
 
Und wenn der Speicherverbrauch konstant bleibt? :stupid:

chaosben 11. Okt 2007 10:19

Re: Warten bis ein Process wieder ready ist
 
Hi!

Erstmal ne Frage vorneweg: willst du eine Konsolen-Sitzung nachspielen? D.h. willst du einen Konsolenprozess starten und dann, nach und nach, Kommandos übergeben?

Falls ja, könnte ich dir mit einer Komponente aushelfen.

gibb 9. Nov 2007 13:12

Re: Warten bis ein Process wieder ready ist
 
Ja genau das will ich.

Das thema ist wieder Aktuell =D

ich habe das nämlich mit der möglichkeit kommandos (in cmd '&&') zu verknüpfen gelöst.

nun scheint es jedoch das ganze nicht immer Stabil zu laufen. Ich habe immer wieder Situationen wo mir das GUI einfriehrt leider nicht nachproduzierbar. Ich nehme daher an das es irgendwo in der Konsole etwas passiert. über den komponenten würde ich mich riesig freuen.

lg gibb

chaosben 9. Nov 2007 18:57

Re: Warten bis ein Process wieder ready ist
 
Hier findest du die Quellen für die ConsoleTools. Es kann sein, das da noch Bugs drin sind, aber grundsätzlich sollte es laufen.

gibb 12. Nov 2007 09:25

Re: Warten bis ein Process wieder ready ist
 
Hi ^^'

Hat ein wengl gedauert bis ich begriffen habe das man das nur mit delphi 2006 kompilieren kann ;) weil sonst die widestring units fehlen.


ehm also hast du ein kleines beispiel wie man die komponente benutzt ? resp. wie ich sie initialisiere und ihr anschliessend die konsolen kommandos übergebe ?

lg gibb

chaosben 12. Nov 2007 12:19

Re: Warten bis ein Process wieder ready ist
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich glaube man kann auch die Widestrings auch ignorieren und normale Strings nehmen. (Kommt auf einen Versuch an)

Anbei ein Beispiel mit der cmd.

gibb 13. Nov 2007 08:58

Re: Warten bis ein Process wieder ready ist
 
ich danke dir bei weiteren fragen melde ich mich wieder... ich entwickle jetzt halt im 2006 spielt keine rolle ich kenne das einfach noch nicht sooo gut.

lg gibb

gibb 13. Nov 2007 10:04

Bugreport 1
 
Also ich bin mal so frei und melde dir bugs die ich finde ;)

wenn man schnell 2 kommandos hintereinander ausführt friehrt das gui bis zur verarbeitung ein oder bleibt komplett hängen. Das problem habe ich auch bei meiner Entwicklung der Konsole.

versuche das einmal im cmd.exe das funktioniert da kann man 10 verschiedene befehle eintippen während die Konsole noch beschäftigt ist und es funktioniert trozdem...

chaosben 6. Dez 2007 19:44

Re: Warten bis ein Process wieder ready ist
 
Ok ... dieser Bug wurde soeben gefixt. Danke fürs Melden. :)

gibb 18. Dez 2007 14:19

Re: Warten bis ein Process wieder ready ist
 
Darf ich fragen wie deine Lösung aussieht? Ich brauche deine komponente zur zeit nicht. hast du auch das problem gelöst das man kommandos im vornerein schicken kann und diese anschliessend ausgeführt werden?

chaosben 18. Dez 2007 19:19

Re: Warten bis ein Process wieder ready ist
 
Zitat:

Zitat von gibb
hast du auch das problem gelöst das man kommandos im vornerein schicken kann und diese anschliessend ausgeführt werden?

Genau das ist jetzt möglich, weil mir jemand ;) einen Wink diesbezüglich gegeben hat.

Wie es im Moment aussieht, kannst du dir im SVN ansehen.

gibb 21. Dez 2007 13:09

Re: Warten bis ein Process wieder ready ist
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe das getestet. Und musste leider festellen das du irgendwo immer noch einen Bug hast. Ich habe mir schnell das Prog da unten geschrieben (Ist nichts weiteres als ne While schleife ;) ) und deine konsole ausgetestet starte es einmal normal analysiere den output dann ruffe es in deiner Konsole auf schaue dir den output an und dann gib mehrmals das kommando für den start ein und schaue was passiert. Es wird einfach nur einmal ausgeführt oder mehrmals mit abgeschnittenem output.

lg Severin

chaosben 2. Jan 2008 06:14

Re: Warten bis ein Process wieder ready ist
 
//edit: quatsch ... muss noch mal drüber nachdenken


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:22 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz