AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit CreateProcess

Ein Thema von Patrick · begonnen am 25. Aug 2005 · letzter Beitrag vom 25. Jan 2008
Antwort Antwort
Seite 1 von 3  1 23      
Patrick

Registriert seit: 15. Sep 2003
184 Beiträge
 
Delphi 2010 Professional
 
#1

Problem mit CreateProcess

  Alt 25. Aug 2005, 10:45
Hallo,

Ich verwende die folgende Funktion, um einen CMD-Befehl auszuführen und die Rückmeldung abzufangen.

Delphi-Quellcode:
function GetConsoleOutput(const Command: String; var Output, Errors: TStringList): Boolean;
var StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  SecurityAttr: TSecurityAttributes;
  PipeOutputRead: THandle;
  PipeOutputWrite: THandle;
  PipeErrorsRead: THandle;
  PipeErrorsWrite: THandle;
  Succeed: Boolean;
  Buffer: array [0..255] of Char;
  NumberOfBytesRead: DWORD;
  Stream: TMemoryStream;
begin
  //ShowMessage(command);
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.bInheritHandle := true;
  SecurityAttr.lpSecurityDescriptor := nil;
  //Pipes erzeugen CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
  //Initialisierung StartupInfo
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb:=SizeOf(StartupInfo);
  StartupInfo.hStdInput := 0;
  StartupInfo.hStdOutput := PipeOutputWrite;
  StartupInfo.hStdError := PipeErrorsWrite;
  StartupInfo.wShowWindow := sw_Hide;
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  if CreateProcess(nil, PChar(command), nil, nil, true,
  CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil,
  StartupInfo, ProcessInfo) then
  begin
    result:=true;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);
    //Ausgabe Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do
      begin
        succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Output.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeOutputRead);
    //Fehler Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do
      begin
        succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Errors.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeErrorsRead);
    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end
  else
  begin
    result:=false;
    CloseHandle(PipeOutputRead);
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsRead);
    CloseHandle(PipeErrorsWrite);
  end;
end:
Diesen Befehl gebe in in Command ein:
cmd /c "C:\Programme\MySQL\MySQL Server 4.1\bin\mysqldump.exe" -hlocalhost -ubenutzer -ppasswort --opt "web1db1" > "D:\download\2005-08-24 13-27\web1db1.sql"

Allerdings ist die Rückmeldung weniger schön:
Der Befehl "C:\Programme\MySQL\MySQL" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

Er rafft nicht, dass er die ganze Zeile bearbeiten soll. Wenn ich exact diese Zeile (Ohne das "cmd /c ") in die Eingabeaufforderung eingebe funktioniert es.

Lasse ich im Command meines Programmes das "cmd /c " weg gibt's diese Meldung:
mysqldump: Couldn't find table: ">"
Was auch schwachsinn ist, denn der Befehl ansich ist richtig!

Also wo liegt der Fehler? Bin ich es oder die Api CreateProcess?

[edit=SirThornberry]Neu abgespeichert um Higlighting zu korrigieren. Mfg, SirThornberry[/edit]
Genieße jede Minute deines Lebens, denn sie wird nicht wieder kommen.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#2

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 10:49
lpCommandLine und lpApplicationName beachten!

Sorry, wenn's etwas unverständlich war:
CreateProcess(nil, PChar(command), ... ... es ist gewagt einerseits das Modul wegzulassen und andererseits alles zusammenzupappen. Doku lesen bildet

Ach ja und bei lpApplicationName heißt es dann '<Pfad zur EXE>\cmd.exe' ...
  Mit Zitat antworten Zitat
Patrick

Registriert seit: 15. Sep 2003
184 Beiträge
 
Delphi 2010 Professional
 
#3

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 12:20
Also langsam gehen mir die Optionen aus...

CreateProcess('C:\Windows\System32\cmd.exe',' /c "C:\Programme\MySQL\MySQL Server 4.1\bin\mysqldump.exe" -hlocalhost -ubenutzer -ppasswort --opt "web1db1" > "D:\download\2005-08-24 13-27\web1db1.sql"',... Dabei haben wir wieder diese Meldung:
Der Befehl "C:\Programme\MySQL\MySQL" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

Ich habe es auch direkt probiert:
CreateProcess('C:\Programme\MySQL\MySQL Server 4.1\bin\mysqldump.exe',' -hlocalhost -ubenutzer -ppasswort --opt "web1db1" > "D:\download\2005-08-24 13-27\web1db1.sql"',... Und hier gibt's diese:
mysqldump: Couldn't find table: ">"
Genieße jede Minute deines Lebens, denn sie wird nicht wieder kommen.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#4

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 14:06
Okay, die erste Variante müßte eigentlich funktionieren. Keine Ahnung warum sie es nicht tut. Ist das Programm ein Konsolenprogramm? Wenn ja, kannst du den Output statt über ">" (welches ja nur im Kontext vom CMD funktioniert) auch die Konsolenhandles benutzen, die du in der Struktur zurückgeliefert bekommst. Dazu würde ich den Prozess suspended starten und dann asynchron auslesen. Danach wieder aufwecken und die asynchronen Callbacks sollten den Output erhalten können.
  Mit Zitat antworten Zitat
Patrick

Registriert seit: 15. Sep 2003
184 Beiträge
 
Delphi 2010 Professional
 
#5

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 18:25
Erstmal vielen Dank für deine Ratschläge, aber ... ich verstehe nur Bahnhof. Ich habe die obrige Funktion von Delphi-Source.de geklaut und gebetet, dass sie das tut, was ich will. Ich habe ein wenig Ahnung vom Programmieren und ich weis, es gibt noch viel zu lernen für mich ,aber dies scheint mir ein wenig zu kompliziert zu sein.
Genieße jede Minute deines Lebens, denn sie wird nicht wieder kommen.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#6

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 18:36
Okay, paß auf. Ich werde das mal eben austesten ... es geht dir ja wohl insbesondere um die Ausgabe dieses Konsolenprogramms, richtig?
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#7

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 19:56
Ich verwende diese Methode da sie auch "zwischendurch" die Ausgaben umleitet.

Delphi-Quellcode:
procedure RunConsoleApp(const CommandLine: string; AStrings: TStrings);
type
  TCharBuffer = array[0..MaxInt - 1] of Char;
const
  MaxBufSize = 1024;
var
  I: Longword;
  SI: TStartupInfo;
  PI: TProcessInformation;
  SA: PSecurityAttributes;
  SD: PSECURITY_DESCRIPTOR;
  NewStdIn: THandle;
  NewStdOut: THandle;
  ReadStdOut: THandle;
  WriteStdIn: THandle;
  Buffer: ^TCharBuffer;
  BufferSize: Cardinal;
  Last: WideString;
  Str: WideString;
  ExitCode: DWORD;
  Bread: DWORD;
  Avail: DWORD;
begin
  GetMem(SA, SizeOf(TSecurityAttributes));
  case Win32Platform of
    VER_PLATFORM_WIN32_NT:
      begin
        GetMem(SD, SizeOf(SECURITY_DESCRIPTOR));
        SysUtils.Win32Check(InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION));
        SysUtils.Win32Check(SetSecurityDescriptorDacl(SD, True, nil, False));
        SA.lpSecurityDescriptor := SD;
      end; {end VER_PLATFORM_WIN32_NT}
  else
    SA.lpSecurityDescriptor := nil;
  end; {end case}
  SA.nLength := SizeOf(SECURITY_ATTRIBUTES);
  SA.bInheritHandle := True;
  SysUtils.Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0));
  if not CreatePipe(ReadStdOut, NewStdOut, SA, 0) then
  begin
    CloseHandle(NewStdIn);
    CloseHandle(WriteStdIn);
    SysUtils.RaiseLastWin32Error;
  end; {end if}
  GetStartupInfo(SI);
  SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  SI.wShowWindow := {SW_SHOWNORMAL} SW_HIDE;
  SI.hStdOutput := NewStdOut;
  SI.hStdError := NewStdOut;
  SI.hStdInput := NewStdIn;
  if not CreateProcess(nil, PChar(CommandLine), nil, nil, True,
    CREATE_NEW_CONSOLE, nil, nil, SI, PI) then
  begin
    CloseHandle(NewStdIn);
    CloseHandle(NewStdOut);
    CloseHandle(ReadStdOut);
    CloseHandle(WriteStdIn);
    SysUtils.RaiseLastWin32Error;
  end; {end if}
  Last := '';
  BufferSize := MaxBufSize;
  Buffer := AllocMem(BufferSize);
  try
    repeat
      SysUtils.Win32Check(GetExitCodeProcess(PI.hProcess, ExitCode));
      PeekNamedPipe(ReadStdOut, Buffer, BufferSize, @Bread, @Avail, nil);
      if (Bread <> 0) then
      begin
        if (BufferSize < Avail) then
        begin
          BufferSize := Avail;
          ReallocMem(Buffer, BufferSize);
        end; {end if}
        FillChar(Buffer^, BufferSize, #0);
        ReadFile(ReadStdOut, Buffer^, BufferSize, Bread, nil);
        Str := Last;
        I := 0;
        while (I < Bread) do
        begin
          case Buffer^[I] of
            #0: inc(I);
            #10:
              begin
                inc(I);
                AStrings.Add(Str);
                Str := '';
              end; {end #10}
            #13:
              begin
                inc(I);
                if (I < Bread) and (Buffer^[I] = #10) then
                  inc(I);
                AStrings.Add(Str);
                Str := '';
              end; {end #13}
          else
            begin
              Str := Str + Buffer^[I];
              inc(I);
            end; {end else}
          end; {end case}
        end; {end while}
        Last := Str;
      end; {end if}
      Sleep(1);
      Application.ProcessMessages;
    until (ExitCode <> STILL_ACTIVE);
    if Last <> 'then
      AStrings.Add(Last);
  finally
    FreeMem(Buffer);
  end; {end try/finally}
  CloseHandle(PI.hThread);
  CloseHandle(PI.hProcess);
  CloseHandle(NewStdIn);
  CloseHandle(NewStdOut);
  CloseHandle(ReadStdOut);
  CloseHandle(WriteStdIn);
end; {end procedure}
.. wo hab ich den jetzt her?

Aufruf z.B.:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  RunConsoleApp('cmd.exe /c dir c:\windows\*.*', Memo1.Lines);
end.
...bei dem Umleiten mit ">" konnte ich noch keine Probleme feststellen.

[edit=SirThornberry]Neu abgespeichert um Higlighting zu korrigieren. Mfg, SirThornberry[/edit]
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#8

Re: Problem mit CreateProcess

  Alt 25. Aug 2005, 20:00
@turboPASCAL: Danke. Wieder etwas Zeit gespart
  Mit Zitat antworten Zitat
Patrick

Registriert seit: 15. Sep 2003
184 Beiträge
 
Delphi 2010 Professional
 
#9

Re: Problem mit CreateProcess

  Alt 26. Aug 2005, 15:10
Ich hab's jetzt so aufgerufen
RunConsoleApp('"C:\Programme\MySQL\MySQL Server 4.1\bin\mysqldump.exe" -hlocalhost -uuser -ppasswort --opt "web1db1" > "D:\download\2005-08-26 14-59\web1db1.sql"',Memo1.Lines); Ergebnis:

-- MySQL dump 10.9
--
-- Host: localhost Database: test
-- ------------------------------------------------------
-- Server version 4.1.13a-nt

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
mysqldump: Couldn't find table: ">"

Wenn ich es mit "cmd \c" aufrufe gabs wieder ein bekannten Fehler:
Der Befehl "C:\Programme\MySQL\MySQL" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
Genieße jede Minute deines Lebens, denn sie wird nicht wieder kommen.
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#10

Re: Problem mit CreateProcess

  Alt 26. Aug 2005, 15:23
Was passiert wen Du den cmd /c Befehl weglässt ?
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz