Entwickler-Ecke
Dateizugriff - DOS-Modus in Delphi
chris_davidi - Do 04.09.03 10:08
Titel: DOS-Modus in Delphi
Hallo...
Ist es möglich, in Delphi ein Programm bestimmten Code auszuführen zu lassen, wie es in einer Batch-Datei der Fall ist?
Ich will nämlich ein paar Batch-Befehle hintereinander aufrufen, welche logischerweise im DOS-Modus laufen sollen. Aber so, dass der Anwender es nicht sieht, dass der DOS-Modus mit den Befehlen ausgeführt wird. Geht das? Wenn ja, wie?
Danke für Hilfe.
Gruss
Chris
ShadowThief - Do 04.09.03 10:16
bin mir nicht sicher, is nur so ne idee, aber vielleicht
kanns du mit ShellExecute eine .bat-datei aufrufen, und zwar mit
parameter SW_HIDE.
wie gesagt, nicht probiert, nur so ne ahnung.
shadow.
Tino - Do 04.09.03 10:46
Du kannst die Ausgabe umleiten.
Hier mal ein Klasse die das macht. Der Autor ist mir leider nicht bekannt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141:
| unit ExecuteCommand;
interface
uses Windows, Messages, Sysutils, Classes;
Const MAX_BUFSIZE = $4000;
type TDOSCommand = class( TObject ) private FResponse: TStrings; FCommand : string; FResult : integer; FError : string; FStuff : TStrings; function GetResponse(Index: integer): string; function GetItemCount: integer; function GetStuff(Index: Integer): string; function GetStuffCount: integer; public constructor Create( DOSCommand: string ); destructor Destroy; override; function Execute: integer; procedure AddStuff( Stuff: string ); property Command: string read FCommand; property Count: integer read GetItemCount; property Error: string read FError; property Items[ Index: integer ]: string read GetResponse; default; property Result : integer read FResult; property Stuff[ Index: Integer ]: string read GetStuff; property StuffCount: integer read GetStuffCount; end;
implementation
procedure TDOSCommand.AddStuff(Stuff: string); begin FStuff.Add( Stuff ); end;
constructor TDOSCommand.Create(DOSCommand: string); begin inherited Create; FCommand := DOSCommand; FResponse := TStringList.Create; FStuff:= TStringList.Create; FError := ''; end;
destructor TDOSCommand.Destroy; begin FStuff.Free; FResponse.Free; inherited Destroy; end;
function TDOSCommand.Execute: integer; var SecAttr: TSecurityAttributes; StartupInfo:TStartupInfo; ProcessInfo:TProcessInformation; WriteHandle, ReadHandle: THandle; ReadBuf: array[0..MAX_BUFSIZE] of Char; BytesRead: DWORD; BufSize: DWORD; GetExitCodeResult: DWORD; begin BufSize := MAX_BUFSIZE;
SecAttr.nLength := SizeOf( SecAttr ); SecAttr.lpSecurityDescriptor := nil; SecAttr.bInheritHandle := True;
if not CreatePipe(ReadHandle, WriteHandle, @SecAttr, BufSize) then begin Result := -2; FError := SysErrorMessage( GetLastError ); Exit; end;
FillChar(StartupInfo,SizeOf(StartupInfo), 0); with StartupInfo do begin cb:= SizeOf(StartupInfo); dwFlags:= STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; hStdOutput:= WriteHandle; hStdError:= WriteHandle; wShowWindow:= SW_HIDE; end;
FillChar(ReadBuf, SizeOf(ReadBuf), 0);
if not CreateProcess(nil, PChar(FCommand), nil, nil, True, DETACHED_PROCESS or NORMAL_PRIORITY_CLASS , nil, nil, StartupInfo, ProcessInfo) then begin FError := SysErrorMessage( GetLastError ); Result:= -1 end else begin WaitForSingleObject(ProcessInfo.hProcess, INFINITE); BytesRead := 0; GetExitCodeProcess(ProcessInfo.hProcess, GetExitCodeResult); Result := GetExitCodeResult; CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); ReadFile( ReadHandle, ReadBuf, BufSize, BytesRead, nil); end; CloseHandle(WriteHandle); FResponse.Text := ReadBuf; FResult := Result; end;
function TDOSCommand.GetItemCount: integer; begin Result := FResponse.Count; end;
function TDOSCommand.GetResponse(Index: integer): string; begin Result := FResponse[ Index ]; end;
function TDOSCommand.GetStuff(Index: Integer): string; begin Result := FStuff[ Index ]; end;
function TDOSCommand.GetStuffCount: integer; begin Result := FStuff.Count; end;
end. |
Benutzt kann die Klasse wie folgt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var DosCmd: TDOSCommand; Rslt: Integer; begin DosCmd := TDOSCommand.Create( 'DIR' ); Rslt := DosCmd.Execute; Memo1.Lines.Assign( DosCmd.Response ); end; |
Gruß
Tino
chris_davidi - Do 04.09.03 12:35
Danke. :)
Kannst du mir aber noch ein bißchen helfen?
Wie bekomme ich zum Beispiel das hin, dass diese Befehle ausgeführt werden.
cd \dtr
pkzip fi fi2.txt
Also ein Verzeichniswechsel und wo danach was gepackt wird, nur als Beispiel.
svenson08 - Do 04.09.03 13:46
Du kannst doch anstelle von
| Zitat: |
cd \dtr
pkzip fi fi2.txt
|
auch
| Zitat: |
\dtr\pkzip fi fi2.txt
|
sagen und das dann mittels
Quelltext
1:
| WinExec(PChar(\dtr\pkzip fi fi2.txt"'), SW_Normal); |
das ganze ausführen. wo die Zieldatei erstellt wird, das gibst du mit dem absoluten Pfad zur Zieldatei an.
Oder hab ich was nicht verstanden
chris_davidi - Do 04.09.03 14:00
Ok, nochmal zum Mitschreiben, habe mich eventuell kompliziert ausgedrückt.
Suche eine Möglichkeit, in Delphi durch ein Event, zum Beispiel einen ButtonClick, DOS-Befehle auszuführen. Nach dem Batch-Prinzip eben. Ich will, dass wie in einer Batch-Datei Programm 1 startet, wenn dies beendet ist Programm 2 und so weiter... Dies soll der Anwender aber nicht sehen, sprich, für ihn ist das DOS-Fenster nicht sichtbar (geht ja mit SW_Hide). Nun fehlt nur noch die oben Beschriebene Möglichkeit.
svenson08 - Do 04.09.03 14:38
Vielleicht fürs bessere verständniss, warum DOS-Befehle ? Schließlich musst du keine Dos Box öffnen um Dos Befehle über Delphi auszuführen.
WinExec ist nur eine möglichkeit Externe Befehle auszuführen.
Wenn du mehrer Befehle ausführen willst häng die aufrufe von Winexec einfach hinter einander. Wenn jedoch erst nach beenden des 1. Programms das 2. Programm gestartet wird hilft dir das hier weiter
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| function TForm_Main.WinExecAndWait32(FileName: string): Longword; var zAppName: array[0..512] of Char; zCurDir: array[0..255] of Char; WorkDir: string; StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; begin StrPCopy(zAppName, FileName); GetDir(0, WorkDir); StrPCopy(zCurDir, WorkDir); FillChar(StartupInfo, SizeOf(StartupInfo), #0); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_NORMAL; if not CreateProcess(nil, zAppName, nil, nil, False, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then Result := WAIT_FAILED else begin WaitForSingleObject(ProcessInfo.hProcess, INFINITE); GetExitCodeProcess(ProcessInfo.hProcess, Result); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); end; end; |
Einfach das zu startende Programm bzw. Dos Befehl übergeben.
Sascha
Moderiert von
Tino: Delphi-Tags hinzugefügt.
chris_davidi - Do 04.09.03 14:44
Okay danke... Und wie wäre der Befehl, um das ganze per Schaltfläche zum Beispiel auszuführen. Zum Beispiel den DOS Befehl format c: .
Sorry für die Fragen, bin noch Anfänger. :(
svenson08 - Do 04.09.03 15:22
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin WinExecAndWait32('command /c format c:'): Longword; end; |
wobei dir dann das bestätigen der eingaben die der format habe möchte fehlen. Also die rückfrage die du auf der DOS-Box hast ( soll wirklich formatiert werden y/n, etc.) Das kannst du hierrüber nicht abbilden.
Aber mit deinem pkzip wirds schon funktionieren.
Moderiert von
Tino: Delphi-Tags hinzugefügt.
Tino - Do 04.09.03 17:28
| svenson08 hat folgendes geschrieben: |
| WinExec ist nur eine möglichkeit Externe Befehle auszuführen. |
Und eine schlechte dazu... WinExec sollte, laut Mircosoft, nicht mehr verwendet werden!
Gruß
Tino
Wolff68 - Do 04.09.03 18:31
Also prinzipiell kannst Du mit ShellExecute Auch DOS-Programme aufrufen. Mit entsprechenden Window-Einstellungen kannst dabei das Anzeigen des Dos-Fensters verhindern.
Eine andere Möglichkeit stellt die Komponente
TDosCommand [
http://maxxdelphisite.free.fr/doscmd.htm] dar. Dort hast quasi das Dosfenster in einem TMemo und kannst Commandozeilenbefehle direkt eingeben und ausführen.
(Das TMemo kannst ja ausblenden)
Selbst Antworten auf Abfragen sind damit möglich.
(Wie das Y/N bei Format C: wobei ich hoffe, daß das nicht Sinn deines Treibens ist...)
chris_davidi - Fr 05.09.03 08:46
Danke für die Infos..
WinExecAndWait32 geht bei mir nicht. Es zeigt mir WinExecAndWait32 und Longword als undefinierter Bezeichner an. Wie kann ich es machen, dass es funktioniert?
Bei TDosCommand, ich habe nur die Version für Delphi 5 gefunden. Gibt es das auch für Delphi 3, hat das schon jemand gesehen bzw. probiert?
svenson08 - Fr 05.09.03 10:39
| Zitat: |
| WinExecAndWait32 geht bei mir nicht. Es zeigt mir WinExecAndWait32 und Longword als undefinierter Bezeichner an. Wie kann ich es machen, dass es funktioniert? |
Füg mal in deine uses-Klauses die StdCtrls und ExtCtrls ein. Dann sollte es gehen
chris_davidi - Fr 05.09.03 12:04
Sind eingebunden, trotzdem noch gleiches Problem.
chris_davidi - Fr 05.09.03 13:20
Habe nun eine andere Idee. Würde das gehen?
Ich will per ShellExecute eine Datei aufrufen. Eine bat- Datei.
Delphi-Quelltext
1:
| ShellExecute(Application.Handle, 'open', 'test.bat', nil, nil, SW_SHOW); |
Mit SW_HIDE kann ich das Fenster der bat- Datei verstecken. Danach sollen aber noch andere Sachen laufen.
Es läuft so ab, ...
Ich klicke auf einen Button...
test.bat öffnet sich und soll sich nach beenden schließen
erst dann sollen die restlichen Funktionen vom Buttons ausgeführt werden. Hier mein Code, hoffe jemand kann helfen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.button_wochenClick(Sender: TObject); begin ShellExecute(Application.Handle, 'open', 'test.bat', nil, nil, SW_SHOW); status.Caption:=('... in Arbeit'); ZipMaster1.ZipFileName:='Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.zip'; if not FileExists('intra_deko.txt') then begin ShowMessage('Fehler - Datei intra_deko.txt nicht gefunden! Übertragung vom Host auf PC oder die Dekomprimierung muss fehlerhaft gewesen sein!'); Exit; end; RenameFile('intra_deko.txt', 'Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.txt'); ZipMaster1.FSpecArgs.Add('Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.txt'); ZipMaster1.Add; ShowMessage('Wenn Status "Wert = 1", dann ist alles ok gewesen'); status.Caption:=('Wert = ' + IntToStr(ZipMaster1.SuccessCnt)); end; |
chris_davidi - Di 09.09.03 08:47
Danke. Habe es mir angeschaut und auch die Links zur Microsoft-Seite angeschaut.
Wie binde ich es jedoch ein, nachdem ich auf einen Button geklickt habe, kannst du mir dafür ein Beispiel geben? Werde irgendwie nicht schlau. :(
Tino - Di 09.09.03 09:38
| chris_davidi hat folgendes geschrieben: |
| Wie binde ich es jedoch ein, nachdem ich auf einen Button geklickt habe |
Zuerst musst du die Funktion in einen vorhanden oder einer neuen Unit einfügen. Im OnClick-Event des Buttons rufst du diese Funktion dann einfach auf:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin RunProcessAndWait ('c:\test.bat'); end; |
Gruß
Tino
chris_davidi - Di 09.09.03 09:43
Habe ich gemacht, habe es in die Unit eingebunden und auch das mit dem Quellcode gemacht, sprich, das OnClick-Event. Leider passiert nichts. Delphi zeigt aber keinen Fehler, nur passiert nicht.
Hier mal den Code, damit ihr euch ein Bild machen könnt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ZipMstr, Buttons, ShellApi, StdCtrls, ExtCtrls, ComCtrls;
type TForm1 = class(TForm) Panel1: TPanel; button_wochen: TSpeedButton; ZipMaster1: TZipMaster; title: TLabel; help_button: TSpeedButton; exit_button: TSpeedButton; kw_day: TEdit; kw_year: TEdit; kw: TLabel; Label1: TLabel; wochendaten_label: TLabel; Bevel1: TBevel; Label2: TLabel; Label3: TLabel; mm_month: TEdit; Label4: TLabel; mm_year: TEdit; button_monats: TSpeedButton; Bevel2: TBevel; Animate1: TAnimate; status_text: TLabel; status: TLabel; Bevel3: TBevel; Bevel4: TBevel; SpeedButton1: TSpeedButton; Bevel5: TBevel; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure exit_buttonClick(Sender: TObject); procedure button_monatsClick(Sender: TObject); procedure help_buttonClick(Sender: TObject); procedure button_wochenClick(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); private public end;
var Form1: TForm1; i: integer; implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); begin Caption:='Transfer - ' + GetCurrentDir; i:=0; ZipMaster1.Load_Zip_Dll; end;
procedure TForm1.FormDestroy(Sender: TObject); begin ZipMaster1.Unload_Zip_Dll; end;
procedure TForm1.exit_buttonClick(Sender: TObject); begin Form1.Close; end;
procedure TForm1.button_wochenClick(Sender: TObject); begin if (i) = 1 then begin status.Caption:=('... in Arbeit'); ZipMaster1.ZipFileName:='Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.zip'; if not FileExists('intra_deko.txt') then begin ShowMessage('Fehler - Datei intra_deko.txt nicht gefunden! Übertragung vom Host auf PC oder die Dekomprimierung muss fehlerhaft gewesen sein!'); status.Caption:=('... Fehler'); Exit; end; RenameFile('intra_deko.txt', 'Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.txt'); ZipMaster1.FSpecArgs.Add('Fi' + kw_day.Text + 'kw'+ kw_year.Text +'.txt'); ZipMaster1.Add; ShowMessage('Wenn Status "Wert = 1", dann ist alles ok gewesen.'); status.Caption:=('Wert = ' + IntToStr(ZipMaster1.SuccessCnt)); end; end;
procedure TForm1.button_monatsClick(Sender: TObject); begin status.Caption:=('... in Arbeit'); ZipMaster1.ZipFileName:='Fi' + mm_month.Text + 'kw'+ mm_year.Text +'.zip'; if not FileExists('intra_deko.txt') then begin ShowMessage('Fehler - Datei intra_deko.txt nicht gefunden! Übertragung vom Host auf PC oder die Dekomprimierung muss fehlerhaft gewesen sein!'); Exit; end; RenameFile('intra_deko.txt', 'Fi' + mm_month.Text + 'mm'+ mm_year.Text +'.txt'); ZipMaster1.FSpecArgs.Add('Fi' + mm_month.Text + 'mm'+ mm_year.Text +'.txt'); ZipMaster1.Add; ShowMessage('Wenn Status "Wert = 1", dann ist alles ok gewesen.'); status.Caption:=('Wert = ' + IntToStr(ZipMaster1.SuccessCnt)); end;
procedure TForm1.help_buttonClick(Sender: TObject); begin help.Show; end;
procedure RunProcessAndWait (aFilename: String); var StartupInfo : TStartupInfo; ProcessInfo : TProcessInformation; Result: Boolean; begin FillChar (StartupInfo, SizeOf (TStartupInfo), 0); StartupInfo.cb := Sizeof (TStartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USEPOSITION or STARTF_USESIZE ; StartupInfo.wShowWindow := SW_SHOW;
Result := CreateProcess ( nil, pChar (aFilename), nil, nil, False, NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo );
if Result then WaitForSingleObject (ProcessInfo.hProcess,INFINITE); if ProcessInfo.hProcess <> 0 then CloseHandle (ProcessInfo.hProcess); end;
procedure TForm1.SpeedButton1Click(Sender: TObject); begin RunProcessAndWait('C:\test.bat'); inc(i); end;
end. |
Tino - Di 09.09.03 09:51
Existiert die Datei c:\test.bat auch?
Gruß
Tino
chris_davidi - Di 09.09.03 09:53
Ja, sie existiert... Habe auch mal einfach mal den Pfad zu einer Textdatei eingegeben, kein Erfolg (leider).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!