![]() |
Befehlszeile ausführen
hallo alle zusammen
komme hier nicht weiter r procedure TForm1.Button1Click(Sender: TObject); VAR output,errors: TStringList; sBatchDatei : string; begin Memo2.clear; begin If CheckBox1.Checked then begin Memo2.Lines.add('xxxx.exe -parameter1 '); end; If CheckBox2.Checked then begin Memo2.Lines.add('xxxx.exe -parameter2 '); end; begin sBatchDatei := memo2.lines[0]; output:=TStringList.Create; try errors:=TStringList.Create; if GetConsoleOutput((sBatchDatei), output, errors) then Memo1.Lines.AddStrings(errors); Memo1.Lines.AddStrings(output); finally output.free; errors.free; end; t.free; soweit funzt der code....mein problem ist es sind über 80 zeilen die abgearbeitet werden sollen...und zum schluß als text datei abgespeichert werden. bekomme die schleife nicht hin. |
AW: Befehlszeile ausführen
Guck mal, in meiner Version sind die Einrückungen zwar weg die vermutlich in deinem Original waren, aber trotzdem ist es lesbarer.
Delphi-Quellcode:
Benutze doch bitte die Delphi-Tags (den "Griechenhelm" bei den Toolbuttons im Editor).
procedure TForm1.Button1Click(Sender: TObject);
var output, errors: TStringList; sBatchDatei: string; begin BefehlsMemo.clear; begin If CheckBox1.Checked then begin BefehlsMemo.Lines.add('xxxx.exe -parameter1 '); end; If CheckBox2.Checked then begin BefehlsMemo.Lines.add('xxxx.exe -parameter2 '); end; begin sBatchDatei := BefehlsMemo.Lines[0]; output := TStringList.Create; try errors := TStringList.Create; if GetConsoleOutput((sBatchDatei), output, errors) then AusgabeMemo.Lines.AddStrings(errors); AusgabeMemo.Lines.AddStrings(output); finally output.free; errors.free; end; t.free; // <--- ???? end; end; end; Nachtrag: habe es mal durch den Castalia-Formatierer gejagt. Da fehlten ja noch ein paar end-Statements usw ... |
AW: Befehlszeile ausführen
Danke
habe ich zwar benutzt aber...bestimmt verschoben (zeilen umbruch) t.free; // <--- ???? ist delphi-tags wie gesagt habe einem zeilenumbruch gemacht. |
AW: Befehlszeile ausführen
So, dann widmen wir uns mal dem Code ;)
Tip: man kann den TMemo-Instanzen auch aussagekräftige Namen geben. Hilft dabei den eigenen Code zu verstehen. Bspw.: Memo1 -> AusgabeMemo Memo2 -> BefehlsMemo
Delphi-Quellcode:
Bis auf die fehlenden Checks fällt mir hier eigentlich nix auf.
sBatchDatei := BefehlsMemo.Lines[0];
output := TStringList.Create; try errors := TStringList.Create; if GetConsoleOutput(sBatchDatei, output, errors) then AusgabeMemo.Lines.AddStrings(errors); AusgabeMemo.Lines.AddStrings(output); finally output.free; errors.free; end; Die Zeilen sollen aus dem Memo2 (BefehlsMemo) genommen und ausgeführt werden? Grob wäre das:
Delphi-Quellcode:
Übrigens: du kannst deinen Ausgangsbeitrag noch immer bearbeiten um die Delphi-Tags einzufügen. Ansonsten müssen wir wieder warten bis sich ein Mod erbarmt.
begin
output := TStringList.Create; try errors := TStringList.Create; for i := 0 to BefehlsMemo.Lines.Count -1 do begin sBatchDatei := BefehlsMemo.Lines[i]; if GetConsoleOutput((sBatchDatei), output, errors) then AusgabeMemo.Lines.AddStrings(errors); AusgabeMemo.Lines.AddStrings(output); end; finally output.free; errors.free; end; end; |
AW: Befehlszeile ausführen
danke funzt :-D
|
AW: Befehlszeile ausführen
Zitat:
da die Variable in diesem Fall nicht initialisiert wurde (was eigentlich Delphi auch bemängeln sollte). z.B. statt einem OutOfMemory bekommt man dann vermutlich ein "Zugriffsverletzung bei Adresse soundso" zu sehn. also müßte es eigentlich so aussehn
Delphi-Quellcode:
oder wenigstens so
output := TStringList.Create;
try errors := TStringList.Create; try ... finally errors.free; end; finally output.free; end;
Delphi-Quellcode:
oder so
errors := nil;
output := TStringList.Create; try errors := TStringList.Create; ... finally output.free; errors.free; end;
Delphi-Quellcode:
output := nil;
errors := nil; try output := TStringList.Create; errors := TStringList.Create; ... finally output.free; errors.free; end; |
AW: Befehlszeile ausführen
Das Problem, dass es beim finally knallen kann, hast Du in der letzten von Dir vorgeschlagenen Variante aber genauso.Auch die zweite Variante deckt nicht alle denkmöglichen Probleme 100%ig sauber ab. Und wozu die nil-Zuweisung?
Ich weiss nicht recht - im Prinzip stimmt zwar, was Du schreibst, aber ist nicht ohnehin schon alles verloren, wenn ein simples tstringlist.create fehlschlägt? So etwas mit einem (gar noch geschachtelten) Try finally abzufangen und dann im Programm weiterzumachen, scheint mir eigentlich nicht sehr sinnvoll zu sein. Da wird sicher nichts mehr, also kann man das Ganze doch ebenso gut ohne try finally einfach geich abstürzen lassen, oder liege ich da falsch? |
AW: Befehlszeile ausführen
Du liegst falsch. Free prüft intern auf nil ab, so dass nil-Objekte nicht zerstört werden, es folglich also auch nicht knallt.
|
AW: Befehlszeile ausführen
Wenn schon ein tstringlist.create abstürzt, wird es sowieso bei nächster Gelegenheit knallen. Derartige Fehler abfangen und weitermachen, als wäre nichts gewesen, bringt doch gar nichts.
|
AW: Befehlszeile ausführen
Nee, wieso soll es da knallen?
Free prüft ja auf NIL und überspringt dann das Freigeben. (unter Anderem soll man darum ja auch vorzugsweise .Free und nicht direkt .Destroy aufrufen) [add]ahhhh, wo kommen denn die Beiträge her :shock: ... und DeddyH zustimm[add/] Nja, es geht mehr ums Prinzip. Klar kann bei diesem einfachen TStringLst.Create nicht viel passieren und wenn, dann ist wirklich Vieles schon verloren, aber was ist, wenn in dem Create mal mehr passiert? Beispiel:
Delphi-Quellcode:
... wenn es hier z.B. wegen fehlenden Rechten knallt und dann diese Fehlermeldung durch die nachfolgend auftretende Speicherzugriffsverletzung verdeckt wird, dann hat man ein Problemchen.
fs := TFileStream.Create('dateina.me', ...);
(bei dieser lokalen Variable ist die Chance immerhin nur 1 zu 4 Milliarden, daß diese Variable zufällig schon nil ist) OK, der Debugger hält vielleicht noch bei der ersten Exception kurz an, aber ohne Debugger sieht man nur noch die letzte Exception. [add] Auch wenn bei soeinem einfachem und dennoch extremen Einzelfall eh alles egal ist, sollte man dennoch eine einheitliche Behandlung implementieren. Wenn man es immer so/gleich macht, dann vergißt man es an anderen Stellen nicht, wo es dann mal nicht mehr egal sein könnte. PS: Das Zweite ist nur eine kleine zusätzliche Zeile, ein einziger extrem kurzer ASM/CPU-Befehl und belegt nur sehr wenige Bytes in der EXE, aber es kann eine sehr große positive Wirkung haben. |
AW: Befehlszeile ausführen
Ich verstehe nicht, auf welchen Code-Teil Du Dich beziehst. Wo wird nach einem Fehler einfach weitergemacht? Bin ich blind?
|
AW: Befehlszeile ausführen
@ Himitsu
Im Prinzip gebe ich Dir ja Recht, dass man mögliche Fehler mit try finally abfangen sollte, bei dem von Dir jetzt genannten Beispiel bin ich ganz bei Dir. Bei einem tstringlist.create erscheint es mir nicht sinnvoll @deddyh Wenn vorher nicht nil zugewiesen wird, kann das nur zu Problemen führen, wenn tstringlist.create eine Exception liefert. Und den Fall zu berücksichtigen und irgendwie abzufangen ist eben meiner Meinung nach unnötig, weil das Programm dann nichts sinnvolles mehr produzieren kann, wenn es weiterläuft. Ich würde es so machen:
Delphi-Quellcode:
Wenn das Erstellen der Stringlist eine Exception liefert, dann geht ohnehin nichts mehr. Und dann wird gleich die richtige Exception angezeigt.
output := TStringList.Create;
errors := TStringList.Create; try ... finally output.free; errors.free; end; |
AW: Befehlszeile ausführen
Zitat:
Es kann doch zufällig danach noch was freigegeben werden und dann paßt es wieder.
Delphi-Quellcode:
Jetzt könnte es ab dem nächten Except (von einem Try-Except) weitergehn, da wieder genug Speicher frei ist.
errors := nil;
output := GetMem(1000000000); // grade noch genug try errors := GetMem(100); // das war jetzt zuviel ... finally FreeMem(errors); // hier könnte es ohne :=nil nochmals knallen FreeMem(output); end; Ohne das :=nil könnte es aber passieren, daß es beim
Delphi-Quellcode:
nochmal knallt, dabei die ursprüngliche Fehlerursache/-adresse verfälscht und
FreeMem(errors)
Delphi-Quellcode:
ganicht mehr ausgeführt wird.
FreeMem(output)
du siehst ... ohne das :=nil wird es nur schlimmer und mit kann es besser werden [add] Zitat:
|
AW: Befehlszeile ausführen
Zitat:
|
AW: Befehlszeile ausführen
IIRC gilt dies nicht für lokale Variablen.
|
AW: Befehlszeile ausführen
Zitat:
|
AW: Befehlszeile ausführen
Sonst gäbe es die Warnung "Variable xyz ist möglicherweise nicht initialisiert worden" ja auch gar nicht, weil sinnlos ;)
|
AW: Befehlszeile ausführen
Globale Variablen (auf Heap?) werden initialisiert, da der gesamte Speicher anfangs eh null ist, welcher von Windows kommt.
Klassenfelder werden via ZeroMemory/FillMemory+0 in CreateInstance des Objekts genullt. Lokale Variablen (auf'm Stack) werden nicht initialisiert (abgesehn von sowas wie String/Interface/DynArray, welches immer initialisiert wird) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:58 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