![]() |
Problem mit CreateProcess
Hallo,
Ich verwende die folgende Funktion, um einen CMD-Befehl auszuführen und die Rückmeldung abzufangen.
Delphi-Quellcode:
Diesen Befehl gebe in in Command ein:
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: 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] |
Re: Problem mit CreateProcess
lpCommandLine und lpApplicationName beachten!
Sorry, wenn's etwas unverständlich war:
Delphi-Quellcode:
... es ist gewagt einerseits das Modul wegzulassen und andererseits alles zusammenzupappen. Doku lesen bildet :zwinker:
CreateProcess(nil, PChar(command), ...
Ach ja und bei lpApplicationName heißt es dann '<Pfad zur EXE>\cmd.exe' ... |
Re: Problem mit CreateProcess
Also langsam gehen mir die Optionen aus...
Delphi-Quellcode:
Dabei haben wir wieder diese Meldung:
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"',...
Der Befehl "C:\Programme\MySQL\MySQL" ist entweder falsch geschrieben oder konnte nicht gefunden werden. Ich habe es auch direkt probiert:
Delphi-Quellcode:
Und hier gibt's diese:
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"',...
mysqldump: Couldn't find table: ">" |
Re: Problem mit CreateProcess
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.
|
Re: Problem mit CreateProcess
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.
|
Re: Problem mit CreateProcess
Okay, paß auf. Ich werde das mal eben austesten ... es geht dir ja wohl insbesondere um die Ausgabe dieses Konsolenprogramms, richtig?
|
Re: Problem mit CreateProcess
Ich verwende diese Methode da sie auch "zwischendurch" die Ausgaben umleitet.
Delphi-Quellcode:
:gruebel: .. wo hab ich den jetzt her?
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} Aufruf z.B.:
Delphi-Quellcode:
...bei dem Umleiten mit ">" konnte ich noch keine Probleme feststellen.
procedure TForm1.Button1Click(Sender: TObject);
begin Memo1.Clear; RunConsoleApp('cmd.exe /c dir c:\windows\*.*', Memo1.Lines); end. [edit=SirThornberry]Neu abgespeichert um Higlighting zu korrigieren. Mfg, SirThornberry[/edit] |
Re: Problem mit CreateProcess
@turboPASCAL: Danke. Wieder etwas Zeit gespart :thumb:
|
Re: Problem mit CreateProcess
Ich hab's jetzt so aufgerufen
Delphi-Quellcode:
Ergebnis:
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);
-- 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. |
Re: Problem mit CreateProcess
Was passiert wen Du den cmd /c Befehl weglässt ?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:12 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