Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   ShellExecute (https://www.delphipraxis.net/204573-shellexecute.html)

Kratos 8. Jun 2020 09:39

Delphi-Version: 10.3 Rio

ShellExecute
 
Hallo Leute,

ich bin Delphi-Neuling und habe jetzt schon etliche Forenseiten durchforstet.

Ich möchte aus meinem delphi-Programm heraus eine .bat-Datei ausführen.
In dieser lösche, kopiere und führe ich jeweils eine Textdatei aus.
Das ganze soll über cmd laufen.
Wenn ich die .bat-Datei manuell ausführe, funktioniert alles wie gewünscht.
Aus delphi heraus, passiert nichts. Es bearbeitet meine Dateien nicht und gibt auch keinen Fehler aus.
Laut Debugger durchläuft es aber meine "ShellExecute"-Programmzeile.

Code:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
begin
  try
    ShellExecute(0, 'open', 'cmd', PChar('/c ' + (ParamStr(0) + '_DELETE_COPY_EXECUTE.bat')), nil, SW_SHOWNORMAL);
    ShowMessage('Alte Version gelöscht.');
  except
    ShowMessage('Fehler');
  end;
end;
Wo genau liegt mein Fehler?
Vielen Dank im Voraus für eure Mühen

VG Kratos

Klaus01 8. Jun 2020 09:47

AW: ShellExecute
 
.. wo liegt denn das Batch file?

Welchen Wert spuckt denn shellExecute aus?

Grüße
Klaus

TiGü 8. Jun 2020 09:51

AW: ShellExecute
 
Zitat:

Zitat von Kratos (Beitrag 1466706)
Code:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
begin
  try
    ShellExecute(0, 'open', 'cmd', PChar('/c ' + (ParamStr(0) + '_DELETE_COPY_EXECUTE.bat')), nil, SW_SHOWNORMAL);
    ShowMessage('Alte Version gelöscht.');
  except
    ShowMessage('Fehler');
  end;
end;
Wo genau liegt mein Fehler?

Du wertest den Rückgabewert von ShellExecute nicht aus!

Delphi-Quellcode:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
var
  ExecResult: Integer
begin
  try
    ExecResult := ShellExecute(0, 'open', 'cmd', PChar('/c ' + (ParamStr(0) + '_DELETE_COPY_EXECUTE.bat')), nil, SW_SHOWNORMAL);
    if ExecResult <= 32 then
      ShowMessage('Fehlercode: ' + IntToStr(ExecResult));
    ShowMessage('Alte Version gelöscht.');
  except
    ShowMessage('Fehler');
  end;
end;
Wenn jetzt ein Fehlercode angezeigt wird, kannst du von dort aus weitermachen.
Ich tippe ja auf Nummer 5 (SE_ERR_ACCESSDENIED).
Doku dazu: https://docs.microsoft.com/en-us/win...-shellexecutea

Kratos 8. Jun 2020 09:55

AW: ShellExecute
 
@Klaus01

Das Batch file hab ich parallel zu meiner Programm-exe abgelegt, daher
Delphi-Quellcode:
ParamStr
.

Was meinst du mit Wert bezüglich ShellExecute?
Wo finde ich diesen Rückgabewert?^^


@TiGü

Danke dir. Ich werde es gleich mal versuchen.

Moombas 8. Jun 2020 09:59

AW: ShellExecute
 
Anmerkung: ParamStr(0) gibt einem doch folgendes aus (Pfad ist Beispielhaft): C:\PROGRAM FILES\BORLAND\DELPHI7\PROJECTS\PROJECT1.EXE

Somit kann er die Batch nicht ausführen, denn daraus würde sich ergeben:
(Pfad ist Beispielhaft) C:\PROGRAM FILES\BORLAND\DELPHI7\PROJECTS\PROJECT1.EXE_DELETE_COPY_EXECUTE.bat

Ersetze ParamStr(0) durch ExtractFilePath(ParamStr(0)).
Dann sollte es funktionieren.

Schöner:
Und versuche doch das, was du in der Batch-Datei machst im Delphi-Programm einzubauen. :)

Kratos 8. Jun 2020 10:11

AW: ShellExecute
 
Also ersteinmal vielen lieben Dank für eure ganzen Tipps.

meine Prozedur sieht jetzt so aus:
Code:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
var
  ExecResult: Integer;
begin
  try
    ExecResult := ShellExecute(0, 'open', 'cmd', PChar('/c ' + ExtractFilePath(ParamStr(0) + '_DELETE_COPY_EXECUTE.bat')), nil, SW_SHOWNORMAL);
    ShowMessage(IntToStr(ExecResult));
  except
    ShowMessage('Fehler');
  end;
end;

Leider funktioniert es immer noch nicht.

@Klaus01
Der Rückgabewert beträgt 42.

@Moombas
Ich möchte später mein eigenes Programm schließen, die alte exe löschen, eine neue exe in den Ordner kopieren und anschließend wieder ausführen lassen.
Deswegen hatte ich mir gedacht, dass ich das ganze in eine batch-Datei auslagere und schon mal mit einfachen Textdateien diesen Vorgang übe.^^

Moombas 8. Jun 2020 10:12

AW: ShellExecute
 
@Kratos du wendest es ja auch falsch an:

So wäre es richtig:
Delphi-Quellcode:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
var
  ExecResult: Integer;
begin
  try
    ExecResult := ShellExecute(0, 'open', 'cmd', PChar('/c ' + ExtractFilePath(ParamStr(0)) + '_DELETE_COPY_EXECUTE.bat'), nil, SW_SHOWNORMAL);
    ShowMessage(IntToStr(ExecResult));
  except
    ShowMessage('Fehler');
  end;
end;

Kratos 8. Jun 2020 10:20

AW: ShellExecute
 
@Moombas

Ich habe deine Klammeränderung übernommen.
Jedoch wird die .bat anscheinend immer noch nicht ausgeführt.

Es ist doch richtig, dass meine bat wie folgt lautet:
Programm.exe_DELETE_COPY_EXECUTE.bat?

Moombas 8. Jun 2020 10:42

AW: ShellExecute
 
Nein :) Das war ein Beispiel um zu zeigen, das diese nicht ausgeführt werden kann, weil der Name falsch zusammen gesetzt wird.

Deine .Bat behält deinen gewünschten Namen (_DELETE_COPY_EXECUTE.bat).
Du kannst zur Kontrolle auch temporär dir die Zusammensetzung mal ausgeben lassen (hilft evtl. dabei das zu verstehen):
Delphi-Quellcode:
procedure TForm5.pnlUpdateMessageClick(Sender: TObject);
var
  ExecResult: Integer
begin
  try
    ShowMessage(ParamStr(0) + '_DELETE_COPY_EXECUTE.bat'); //nur zum evtl. besseren Verständnis, kann im eigentlichen Code nachher raus!
    ShowMessage(ExtractFilePath(ParamStr(0)) + '_DELETE_COPY_EXECUTE.bat'); //nur zum evtl. besseren Verständnis, kann im eigentlichen Code nachher raus!
    ExecResult := ShellExecute(0, 'open', 'cmd', PChar('/c ' + ExtractFilePath(ParamStr(0)) + '_DELETE_COPY_EXECUTE.bat'), nil, SW_SHOWNORMAL); //so wäre es richtig, der Dateiname bleibt "_DELETE_COPY_EXECUTE.bat"
    if ExecResult <= 32 then
      ShowMessage('Fehlercode: ' + IntToStr(ExecResult));
    ShowMessage('Alte Version gelöscht.');
  except
    ShowMessage('Fehler');
  end;
end;

Der schöne Günther 8. Jun 2020 10:43

AW: ShellExecute
 
Ich will kein Schlauscheißer sein, aber auf lange Sicht wirst du nicht glücklich wenn sich die Fehleranalyse auf "Geht irgendwie" und "Geht irgendwie nicht" beschränkt. Speicher dir das ganze String-Gewurstel doch in einer extra Variable und nutze den Debugger. Dann kannst du dir den Inhalt der Variable anschauen und siehst wo das Problem ist.

Kratos 8. Jun 2020 11:05

AW: ShellExecute
 
Ihr glaubt ja gar nicht wie verdammt bescheuert ich bin!
Ich hatte vor einiger Zeit auf einer anderen Platte ein Backup meines Projekts angelegt.
An meinem Backup arbeite ich ja aber nicht aktiv, sondern arbeite auf einer ganz anderen Partition. Ich hab die bat in meinen Backup-Ordner gelegt.
Oh my fcking god!

Es funktioniert jetzt :D


Ich bedanke mich dennoch bei allen für eure großartige Hilfe, besonders bei @Moombas.
Deine detailreiche Erklärung hat mich trotzdem weiter gebracht :)

VG Kratos

Moombas 8. Jun 2020 11:08

AW: ShellExecute
 
Naja Detailreich fand ich sie nun nicht.

Generell kann ich dir bei soetwas nur empfehlen, wie es Günther schrieb: Schau dir das wo es nicht funktioniert im Debugger an und/oder gebe einfach mal aus (hier der Pfad+Dateiname), was du an eine Funktion übergibst (sofern generiert und nicht fix übergeben).

Dann wird man in der Regel schnell fündig wo der Hase im Pfeffer liegt.

jaenicke 8. Jun 2020 11:45

AW: ShellExecute
 
Zitat:

Zitat von Kratos (Beitrag 1466723)
Ich hatte vor einiger Zeit auf einer anderen Platte ein Backup meines Projekts angelegt.
An meinem Backup arbeite ich ja aber nocht aktiv, sondern arbeite auf einer ganz anderen Partition.

Dafür gibt es Versionsverwaltungen wie Git oder SVN, dann braucht man kein Backup in Form von kopierten oder gezippten Quelltextverzeichnissen und man kann auch viel bequemer damit arbeiten...
https://entwickler-ecke.de/topic_Kur..._115462,0.html

Moombas 8. Jun 2020 11:54

AW: ShellExecute
 
Zitat:

Zitat von Kratos (Beitrag 1466712)
@Moombas
Ich möchte später mein eigenes Programm schließen, die alte exe löschen, eine neue exe in den Ordner kopieren und anschließend wieder ausführen lassen.
Deswegen hatte ich mir gedacht, dass ich das ganze in eine batch-Datei auslagere und schon mal mit einfachen Textdateien diesen Vorgang übe.^^

@Kratos: Da dein Problem behoben zu sein scheint, möchte ich nochmal hier drauf eingehen (s.o.).
Das hört sich nach einer Update-Routine an.
Klingt evtl. etwas merkwürdig aber ich würde es (gerade zum Lernen) an deiner Stelle auch in Delphi schreiben.
Insbesondere wenn solche Update-Routinen später etwas umfangreicher werden, z.B. mit der Einbindung einer Möglichkeit des Rollback, falls das Update fehlschlägt etc. wird das in einer Batch nachher schnell unübersichtlich oder auch nicht praktikabel.

Kratos 8. Jun 2020 12:15

AW: ShellExecute
 
@jaenicke

Git und SVN sind mir bekannt, auch wenn ich diese noch nicht genutzt habe.
Danke für deinen Tipp, nun scheint es wohl doch an der Zeit zu sein, dass ich mich näher damit beschäftige.^^

@Moombas

Du liegts richtig. Ich wollte eine abgespeckte Update-Routine implementieren.
Wenn ich dies ebenfalls in delphi programmieren soll, sollte man dies gleich mit in das Hauptprogramm mit rein nehmen oder sollte ich ein weiteres Programm schreiben, welches ich aus meinem Hauptprogramm heraus starte?

Moombas 8. Jun 2020 12:20

AW: ShellExecute
 
Du kannst ja eine Datei nicht überschreiben, während diese noch läuft. Daher kommst du über eine separate Exe (oder ähnliches) nicht drum herum.
Aber eben diese würde ich trotzdem halt in Delphi schreiben, weil es für dich "Training" bedeutet und der Umfang dessen mit der Zeit steigen wird (je nach Programmumfang).

Es ist zudem einfacher, ein solches Programm mit wachsen zu lassen, als dieses komplett nachträglich mit einzubauen.

Kratos 8. Jun 2020 12:51

AW: ShellExecute
 
@Moombas

Alles klar, danke dir!
Das dachte ich mir schon.
Dann werde ich das so handhaben.

jaenicke 8. Jun 2020 12:55

AW: ShellExecute
 
Zitat:

Zitat von Moombas (Beitrag 1466736)
Du kannst ja eine Datei nicht überschreiben, während diese noch läuft. Daher kommst du über eine separate Exe (oder ähnliches) nicht drum herum.

Man kann aber die Datei normalerweise umbenennen während sie läuft. Man kann auch die gleiche Exe mit Parametern erneut starten und hat dann zwar mehrere Instanzen, aber immer noch nur eine Exe.

Moombas 8. Jun 2020 13:57

AW: ShellExecute
 
Ok, das mit den Parametern kenne/weiß ich. Das mit dem umbenennen war mir neu, weil mir das bisher noch nie als use-case aufgetreten ist.

Wenn ich @Jaenicke also richtig verstehe: Programm starten -> In diesem benennt die Update-Prozedur die eigene Exe um, kopiert die neue rein und startet diese und beendet die alte.
Die neue löscht dann wiederum die umbenannte exe und alles ist schick mit nur einer exe-Datei.

Hmm, hört sich interessant an.
Ich für meinen Teil bleibe aber wohl eher dabei das zu splitten.

himitsu 8. Jun 2020 14:54

AW: ShellExecute
 
Auf Netzlaufwerken, bzw. umgeleiteten Unterverzeichnisen zu Einem, da geht das mit dem Umbenennen eventuell oft nicht. (kommt drauf an, wie der Server am enderen Ende die Sperren behandelt)

Es gibt hier im Forum auch irgendwo eine Komponente, welche das mit dem Update handelt.
> Hier im Forum suchenUpdater irgendwas

Und ansonsten mehrere Threads, wo man den einen oder anderen hilfreichen Hinweis/Tipp bestimmt findet.

Kratos 9. Jun 2020 07:56

AW: ShellExecute
 
Danke euch!
Ich werde mir die Komponente mal anschauen :)

VG Kratos

creehawk 26. Mär 2021 15:27

AW: ShellExecute
 
Ich wollte jetzt nicht einen neuen Threat für Shell Execute aufmachen , daher:

Die folgende Codezeile

Code:
   ShellExecute(Handle,'open', PChar('C:\Users\....\Projekte\PKM\XML\json2xml.exe modinfo.json'), nil, nil, SW_normal);
ruft das Programm json2xml.exe auf das die Datei info.json in eine XML umwandelt. Sollte man denken. Fehlercode 2 wird geliefert, ergo "Datei nicht gefunden".

WENN ich das zu Fuß mache - Windows+R - oder cmd aufrufe im ensprechenden Verzeichns und dann eben "json2xml.exe modinfo.json" starte eght das anstandslos.

Was zum Henker mache ich falsch?

DeddyH 26. Mär 2021 15:41

AW: ShellExecute
 
Du musst das aufzurufende Programm und die Parameter trennen.
Delphi-Quellcode:
ShellExecute(Handle,'open', PChar('C:\Users\....\Projekte\PKM\XML\json2xml.exe'), 'modinfo.json', nil, SW_normal);
Wobei die relative Pfadangabe natürlich auch noch ein Problem darstellen kann.

creehawk 26. Mär 2021 15:54

AW: ShellExecute
 
Gefällt ihm auch nicht. Jetzt kommt Fehlercode 42.... Woran erinnert micht das?

creehawk

TiGü 26. Mär 2021 15:59

AW: ShellExecute
 
Zitat:

Zitat von creehawk (Beitrag 1486150)
Gefällt ihm auch nicht. Jetzt kommt Fehlercode 42.... Woran erinnert micht das?

Das du die Doku nicht gelesen hast?
Zitat:

If the function succeeds, it returns a value greater than 32.
https://docs.microsoft.com/en-us/win...-shellexecutea

Delphi.Narium 26. Mär 2021 16:00

AW: ShellExecute
 
Wo liegt denn die modinfo.json?

Eventuell gibst Du da auch mal den vollständigen Pfad an.

Oder: https://docs.microsoft.com/en-us/win...-shellexecutea

Das Arbeitsverzeichnis anstelle des dritten Nil?

creehawk 26. Mär 2021 16:09

AW: ShellExecute
 
Also das mit der 42 ist mir schon klar. Was aber nichts daran ändert das die Funktion kein Ergbnis zeitigt. Und ich verwende ShellExecute und nicht ShellExecuteA
Ersteres liefert mit 42, letzteres 2.

Und selbst wenn ich überall in Shellexeute den Pfad angebe passiert nichts.

Das Fenster geht allerdings sehr kurz auf - und wieder zu.
creehawk

Delphi.Narium 26. Mär 2021 16:37

AW: ShellExecute
 
Die Parameter für ShellExecute, ShellExecuteA und ShellExecuteW sind gleich, ebenfalls deren Rückgabewerte und deren Verhalten im Erfolgs- bzw. Fehlerfalle. Sind unterscheiden sich im Typ der Aufrufparameter zwischen PChar, PAnsiChar und PWideChar. Ein Blick in die Delphisourcen kann hier hilfreich sein.

Und Fenster kurz auf bedeutet nur, dass nicht auszuschließen ist, dass ShellExecute arbeitet, das ist aber nicht gleichbedeutend damit, dass auch json2xml.exe korrekt arbeiten kann bzw. muss.

Es wäre also zu prüfen, ob der Aufruf von ShellExecute scheitert oder dieser zwar erfolgreich ist, aber json2xml.exe bei der Erledigung seiner Aufgabe ein Problem hat.

creehawk 26. Mär 2021 17:12

AW: ShellExecute
 
Tja, danke für die vielen Antworten.

Bleibt letztlich wohl nur das die json2xml.exe ein Problem hat. Warum das dann allerdings zu Fuß geht...

creehawk

Delphi.Narium 26. Mär 2021 17:19

AW: ShellExecute
 
Zufuß geht, weil Aufruf zufuß korrekt ist.

Wenn's per ShellExecute nicht geht, liegt es daran, dass dann dort der Aufruf nicht korrekt ist, etwas anderes in der Systemumgebung erwartet wird, ...

Viele mögliche Ursachen.

Schonmal 'ner Batch für den Aufruf des Programmes geschrieben?
Dort am Ende ein Pause eingefügt, dann die Batch per ShellExecute aufgerufen und, vor dem Wegdrücken der Pausemeldung, mal die Ausgabe angesehen?

Hilft oft unermesslich viel weiter.

himitsu 26. Mär 2021 17:28

AW: ShellExecute
 
Zitat:

Zitat von DeddyH (Beitrag 1486149)
Du musst das aufzurufende Programm und die Parameter trennen.
Delphi-Quellcode:
ShellExecute(Handle,'open', PChar('C:\Users\....\Projekte\PKM\XML\json2xml.exe'), 'modinfo.json', nil, SW_normal);
Wobei die relative Pfadangabe natürlich auch noch ein Problem darstellen kann.

Den zweiten Satz gelesen?


Kein Arbeitsverzeichnis angegeben und auch bei modinfo.json kein Pfad.

DieDolly 26. Mär 2021 17:29

AW: ShellExecute
 
Wie ist denn dein exakter Aufruf? Hast du da wirklich \....\ im Pfad? Hast du Leerzeichen im Pfad?
Versuch mal PathCanonicalize. Damit bekommst du den absoluten Pfad aus dem relativen Pfad. Wobei \....\ eh komisch ist. Müsste es nicht \..\..\ heißen?

Dalai 26. Mär 2021 17:30

AW: ShellExecute
 
Das Arbeitsverzeichnis wird vermutlich ein anderes sein. Relative Pfade sind nahezu immer eine schlechte Idee [EDIT](ebenso wie hartkodierte Pfade)[/EDIT].

Grüße
Dalai

KodeZwerg 26. Mär 2021 17:50

AW: ShellExecute
 
die punkte sind doch sein username, war leider ansicode;)
schau in msdn, benenne alles wie es sich gehört, dann klappt es auch.
42 = die externe exe wurde gestartet
das sie sich schließt liegt an deinem fehlenden angaben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:47 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