Announcement

Collapse
No announcement yet.

Dosfenster einlesen? !Beispiel!

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dosfenster einlesen? !Beispiel!

    Hallo
    Ich hab zwar schonmal das gleiche unter allgemein gestellt da wurde mir nur leider kein beispiel genannt sonder gesagt ich könnte es mit verschiedenen API Befehlen schaffen! Also bitte ich euch ein kurzes beispiel wie ich das dosfenster öffnen muss(so das man es nirgens sieht währe gut), die abfrage des textes(will ich mehrmals machen weil dort eine prozent anzeige ableuft die ich übernehemen will), und wie man es schließt(mit keysend enter senden werd ich auch alleine schaffen nur wie man das fenster dann in den vordergrund setzt muss ich noch wissen das die taste auch ans richtige fenster gesendet wird).

  • #2
    Hallo,

    ich habe bewusst in der vorherigen Antwort nur die API-Funktionen genannt, da über die Suche nach ReadConsoleOutput hier im FORUM ein vollständiges Beispiel gefunden werden kann. Und nicht nur dass, genau 3 Zeilen unter dieser Frage steht eine ähnliche Frage, die bereits beantwortet wurde. Ich würde daher zuerst einige Minuten im FORUM suchen, <b>bevor</b> eine neue Frage gestellt wird ;-

    Comment


    • #3
      Hi

      Richtig, ein bißchen Eigenkreativität schadet nichts :-) man kann nur mehr lernen :-))

      Gruß Hage

      Comment


      • #4
        Alles schön und gut aber weitergekommen bin ich trotzdem nicht! Hab zwar das beispiel kopiert und probiert zu starten aber er erkennt die Deklarationen (zb. pcinfo) nicht an! Außerdem weiß ich nicht ganz recht wie ich meine consolen anwendung öffnen soll und wo ich welchen wert dann der procedur hinzufügen muss?! Wass toll währe, währen zwei programmteile: 1. die eröffnung eines konsolenfenster und das starten der consolenanwendung(mit übergabe von parametern) und 2. dann die abfrage des gesamten bildschirms in ein memo! Die konsole soll nicht sichtbar sein! Die tasten die vorm beenden übergeben werden müssen bekomme ich bestimmt noch selber hin! Ich bin halt noch blutiger anfäger im bereich konsolen in ein Programm einbinden..

        Comment


        • #5
          Hallo,

          hinter <i>pcinfo</i> verbirgt sich ein Zeiger auf eine <i>cinfo</i> alias TCharInfo-Struktur. Diese Deklaration rüstet Object Pascal mit der aus dem Win32-SDK übernommenen Struktur nach (d.h. das in C/C++ vorliegende Microsoft-Beispiel wird nur nachgebaut):
          <pre>
          (*
          TCharInfo = packed record
          case Integer of 0: (UnicodeChar: WCHAR; Attributes: Word);
          1: (AsciiChar: CHAR);
          end;
          *)

          type
          // Pufferstruktur für die ausgelesenen Daten
          cInfo = array[1..MAXINT div SizeOf(TCharInfo)] of TCharInfo;
          pcInfo = ^cInfo;
          </pre>
          Nun muss nur noch eine neue Console angefordert werden, in der die über <b>CreateProcess</b> ausgeführte Anwendung laufen soll. Danach kann über <b>GetStdHandle</b> das Handle auf die Console zwischengepuffert werden, um später den Inhalt auslesen zu können:
          <pre>
          (* Schritt 1: DOS-Programm in einem neuen Consolen-Fenster
          ausführen und ein Handle auf die Standardausgabe
          in diesem Fenster sichern. *)

          procedure TForm1.BtnDOSStartClick(Sender: TObject);
          var
          szAppName : array[0..512] of Char;
          aSI : TStartupInfo;
          begin
          BtnDOSStart.Enabled := False;
          // neue Console für diesen Process anfordern
          if AllocConsole then begin
          // auszuführender DOS-Befehl
          StrPCopy(szAppName, 'command.com /c dir');
          // TStartupInfo-Datenstruktur initialisieren
          FillChar(aSI, Sizeof(aSI), #0);
          with aSI do begin
          cb := Sizeof(aSI);
          dwFlags := STARTF_USESHOWWINDOW;
          wShowWindow := SW_SHOWDEFAULT;
          end;
          // Programm als neuen Process in der Console starten
          if CreateProcess(nil, szAppName, nil, nil, False, // handle inheritance flag
          CREATE_SEPARATE_WOW_VDM or NORMAL_PRIORITY_CLASS,
          nil, nil, aSI, aPI) then begin
          // Überschrift des Consolen-Fensters setzen
          SetConsoleTitle(PChar('DIR als Consolen-Anwendung'));
          // Handle für den Standard-Output der Console holen
          hConsole := GetStdHandle(STD_OUTPUT_HANDLE);
          BtnDOSStop.Enabled := true;
          BtnDOSGrab.Enabled := true;
          end
          else
          begin
          BtnDOSStart.Enabled := true;
          end;
          end;
          StatBar.SimpleText := 'Console wurde gestartet...';
          end;
          </pre>
          P.S: Das vollständige Beispielprojekt mit der ausführlicheren Beschreibung findet sich wie bereits gesagt wurde in meinem Buch <i>Delphi Win32-Lösungen</i>

          Comment


          • #6
            Soweit klappt alles bis auf das aPi nicht vom Compiler akzeptiert wird!<b><br>(Compilermeldung: [Fehler] Unit1.pas(71): Die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen)</b><br> Obwohl ich sie als TProcessInformation deklariert habe und vorher volgendes eingefügt habe so wies in der hilfe steht!:
            <b><br>
            type <br>
            TProcessInformation = record<br>
            hProcess: THandle;<br>
            hThread: Thandle;<br>
            dwProcessId: DWord;<br>
            dwThreadld: DWord;<br>
            end;</b>
            <br>
            Was ist Falsch

            Comment


            • #7
              Hallo,

              die <b>TProcessInformation</b>-Struktur wird in der Delphi-Unit <b>Windows</b> deklariert:
              <pre>
              PProcessInformation = ^TProcessInformation;
              _PROCESS_INFORMATION = record
              hProcess: THandle;
              hThread: THandle;
              dwProcessId: DWORD;
              dwThreadId: DWORD;
              end;
              {$EXTERNALSYM _PROCESS_INFORMATION}
              TProcessInformation = _PROCESS_INFORMATION;
              PROCESS_INFORMATION = _PROCESS_INFORMATION;
              {$EXTERNALSYM PROCESS_INFORMATION}
              </pre>
              Bei der in Windows.pas stehenden Deklaration von <b>CreateProcess</b> muss man beachten, das der TProcessInformation-Parameter im Gegensatz zu TStartupInfo <b>nicht</b> als Const, sondern als <b>Var</b> deklariert wird:
              <pre>
              function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
              lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
              bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
              lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
              var lpProcessInformation: TProcessInformation): BOOL; stdcall;
              </pre>
              Somit muss <i>aPI</i> als Variable bzw. Objektfeld vom Typ TProcessInformation deklariert werden.

              P.S: Das o.g. Programm wurde mit Delphi 3 entwickelt und mit Delphi 5 erneut getestet - es liegt also nicht am Programm ;-)<br>
              &#10

              Comment


              • #8
                Erstmal Danke für die Hilfe! <br>
                Ich denke dies ist meine Letzt Frage zu diesem Thema!<br>
                Es haben sich noch zwei unklarheiten gebildet:<br><br>
                1. Warum und wie kann ich das unterbinden das beim schließen der Konsole mein Programm auch beendet wird?(Ich habe sogar den Quelltext in ein TThreat Objekt gepackt)<br>
                2. Wie kann ich das Fenster für den Benutzer unsichtbar halten? (Ich habe wShowWindow := WS_Hide eingegeben und es wird immer noch angezeigt!)<br><br>
                Und nochmal danke für die Hilfe ich hoffe nach dieser antwort packe ich es

                Comment


                • #9
                  Hallo,

                  das eigene Programm hat über <b>AllocConsole</b> eine Console aktiviert und zusätzlich Process- und Thread-Handle angefordert. Daher muss sich das eigene Programm auch an die von Win32 aufgestellten Spielregeln halten und alles in der richtigen Reihenfolge wieder freigeben. Über den Aufruf von <b>WaitforSingleObject</b> wird sichergestellt, dass erst dann aufgeräumt wird, wenn das Consolen-Fenster geschlossen wurde:
                  <pre>
                  (* Schritt 3: Consolen-Fenster schließen *)

                  procedure TForm1.BtnDOSStopClick(Sender: TObject);
                  var
                  dwResult : DWORD;
                  begin
                  try
                  // Sicherheitsabfrage: Programm bereits zu Ende ?
                  WaitforSingleObject(aPI.hProcess, INFINITE);
                  // Exit-Code des Consolen-Programms holen
                  GetExitCodeProcess(aPI.hProcess, dwResult);
                  // allozierte Handles freigeben
                  CloseHandle(aPI.hProcess );
                  CloseHandle(aPI.hThread );
                  CloseHandle(hConsole);
                  // Consolenobjekt freigeben
                  FreeConsole;
                  BtnDOSStop.Enabled := False;
                  BtnDOSGrab.Enabled := False;
                  BtnDOSStart.Enabled := True;
                  except
                  MessageBeep($FFFFFFFF);
                  end;
                  StatBar.SimpleText := 'Console wurde geschlossen!';
                  end;
                  </pre>
                  Ein Fenster kann auch "unsichtbar" gemacht werden, indem man es mit negativen Koordinaten-Werte aus dem sichtbaren Bereich des Desktops verschiebt. Dies sollte immer dann funktionieren, wenn alle anderen Möglichkeiten ohne Erfolg ausgeschöpft wurden

                  Comment

                  Working...
                  X