Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Datei per Doppelklick dem bereits geöffneten Programm übergeben (https://www.delphipraxis.net/191314-datei-per-doppelklick-dem-bereits-geoeffneten-programm-uebergeben.html)

Friday 2. Jan 2017 12:30

Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Hallo,
ich lasse nur eine Instanz meiner Anwendung zu, mit folgendem Code:
Code:
Initialization
  mHandle:=CreateMutex(nil,True,'Programmname');
  if GetLastError=ERROR_ALREADY_EXISTS then
    Halt;

finalization
  if mHandle<>0 then
    CloseHandle(mHandle)
Wenn ich eine Datei mit der Endung die meinem Programm zugewiesen ist, doppelklicke öffne ich sie in dem ich ParamStr(x) in der FormShow Routine meiner Anwendung überprüfe und dann die Datei-Öffnen-Routine aufrufe.

Bloss wie mache ich es wenn ich auf eine Datei meiner Endung doppelklicke und mein Programm bereits geöffnet ist? Ich müsste for dem "Halt" die ParamStr(x) auslesen und der ersten Instanz meines Programmes übergeben. Ist das ein Fall für SharedMemory oder die COM Schnittstelle oder gibt es auch einen einfacheren / direkteren Weg an den ich jetzt nicht denke?

danke schonmal

DeddyH 2. Jan 2017 12:37

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
WM_COPYDATA fällt mir da spontan ein. Beispiele sollten sich im Forum finden lassen.

himitsu 2. Jan 2017 13:21

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
IPC

mail-slots
pipes
messages
named MMF oder unnamed MMF via message (RegisterWindowMessage+SendMessage)
uvm.

Und mit Delphi-Referenz durchsuchenHalt beendet man kein VCL-Programm, jedenfalls nicht, wenn man es "ordentlich" machen will.
Entweder wie in der OH genannt oder garnicht erst ins
Delphi-Quellcode:
Application.Run
reinlaufen.

Der schöne Günther 2. Jan 2017 13:23

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von himitsu (Beitrag 1357751)
Und mit Halt beendet man kein VCL-Programm, jedenfalls nicht, wenn man es "ordentlich" machen will.

Was ist denn daran nicht ok? Vor allem wenn er es im init-Block seiner DPR anscheinend macht.

Mikkey 2. Jan 2017 13:36

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Ich würde das mit GlobalAlloc und einer WM_USER-Nachricht machen. WM_COPYDATA erfordert ein eigenes Fenster, das Dir beim Programmbeginn noch nicht zur Verfügung steht.

Ablauf:
Code:
GlobalAlloc(ausreichende Größe, um den übergebenen Dateipfad darin unterzubringen)
GlobalLock()
Pfad in den Speicherbereich übertragen
GlobalUnlock()
SendMessage(WM_USER+x, Handle aus GlobalAlloc)

Verarbeiten im empfangenden Programm:
GlobalLock
herauskopieren des Inhalts
GlobalUnlock
PostMessage (z.B: WM_USER+x+1)
Return

GlobalFree()
Beenden

Luckie 2. Jan 2017 13:52

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von Mikkey (Beitrag 1357756)
WM_COPYDATA erfordert ein eigenes Fenster, das Dir beim Programmbeginn noch nicht zur Verfügung steht.

Wieso? Sein Programm läuft doch schon, also ist auch ein Fenster da, an das man die Nachricht schicken kann.

Mikkey 2. Jan 2017 14:04

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von Luckie (Beitrag 1357759)
Zitat:

Zitat von Mikkey (Beitrag 1357756)
WM_COPYDATA erfordert ein eigenes Fenster, das Dir beim Programmbeginn noch nicht zur Verfügung steht.

Wieso? Sein Programm läuft doch schon, also ist auch ein Fenster da, an das man die Nachricht schicken kann.

Zitat aus der MS-Doku:
Zitat:

Parameters
wParam
A handle to the window passing the data.

himitsu 2. Jan 2017 17:09

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Auch dein SendMessage braucht ein Window-Handle, genauso wie WM_COPYDATA.

Mikkey 2. Jan 2017 17:40

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von himitsu (Beitrag 1357800)
Auch dein SendMessage braucht ein Window-Handle, genauso wie WM_COPYDATA.

Aber nur für das Zielfenster, das sich mit FindWindow leicht herausfinden lässt. Bei WM_COPYDATA ist ein Fenster des Senders erforderlich (warum auch immer).

DeddyH 2. Jan 2017 17:55

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Von "erforderlich" kann ich im MSDN aber nirgends etwas lesen. Vielmehr verstehe ich das so, dass man hier optional das Fensterhandle des Senders hinterlegen kann. Ich würde es einfach mal mit einer 0 probieren, sollte das nicht klappen, mit HWND_MESSAGE oder so.

Mikkey 2. Jan 2017 18:57

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von DeddyH (Beitrag 1357806)
Von "erforderlich" kann ich im MSDN aber nirgends etwas lesen. Vielmehr verstehe ich das so, dass man hier optional das Fensterhandle des Senders hinterlegen kann. Ich würde es einfach mal mit einer 0 probieren, sollte das nicht klappen, mit HWND_MESSAGE oder so.

Schon gemacht? Dann nehme ich alles zurück. Die Methode per GlobalAlloc ist etliche Male in der Praxis erprobt. Nennenswert mehr Code ist damit auch nicht verbunden.

a.def 2. Jan 2017 19:45

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Ich benutze für dieses Problem auch WM_COPYDATA.

Situation

- Programm "A" ist gestartet
-- in der DPR-Datei wird geprüft, ob es schon eine aktive Instanz gibt. Hier nein, also Programm ausführen
- erneut Doppelklick auf Programm "A" ruft Programm "A" erneut auf.
-- in der DPR-Datei wird wieder auf eine aktive Instanz geprüft. Hier gibt es nun eine, also sende Daten mit WM_COPYDATA und führe die zweite Instanz von "A" nicht weiter => also beenden.
- die erste aktive Instanz von "A" wertet nun die von der zweiten Instanz "A" übergebenen Daten aus.

Luckie 2. Jan 2017 20:19

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Hier im Forum gibt es schon genug Beispiele für dieses Problem mit WM_COPYDATA. Es scheint also zu funktionieren.

HolgerX 2. Jan 2017 20:51

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Hmm..

Sowas ähnliches hab ich mal gemacht, jedoch nicht um einen String zu übergeben, sondern, um die bereits laufende Applikation nach Vorne zu holen.

Beim Start verwende ich

Delphi-Quellcode:
  {Register a custom windows message}
  FAppMyMsg := RegisterWindowMessage(FAppProgName);
Wenn der Mutex dann bereits vorhanden ist, wird

Delphi-Quellcode:
SendMessage(HWND_BROADCAST,RegisterWindowMessage(FAppProgName),0,0);
Aufgerufen.

Da die WindowsMessage nur von selben Programm gekannt wird, reagiert auch nur dieses darauf.

himitsu 3. Jan 2017 01:18

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von Luckie (Beitrag 1357829)
Hier im Forum gibt es schon genug Beispiele für dieses Problem mit WM_COPYDATA. Es scheint also zu funktionieren.

Eventuell muß man auch noch ChangeWindowMessageFilterEx verwenden, aber wird bei vielen prozessübergreifenden Messages im MSDN sowieso immer mit erwähnt.

Luckie 3. Jan 2017 01:23

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Das habe ich noch nie hier im Forum gesehen. Muss also auch ohne gehen. :wink:

himitsu 3. Jan 2017 01:30

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Meistens gibt es das Problem nur bei evaluierten Anwendungen.

NichtAdminAnwendung zu AdminAnwendung
AnwendungInUserContextA zu AnwendungInUserContextB

Aber schaden kann es auch nicht. :angle:

Luckie 3. Jan 2017 01:38

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Hä? Von NormalUser zu Admin? Jetzt wird es strange. User zu User. OK. Kein Problem. Aber User zu Adim? Das sollte Windows zu verhindern wissen. Zumindest ohne Passworteingabe.

Friday 3. Jan 2017 10:37

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
danke für die vielen Vorschläge.
Mit WM_COPYData funktioniert es an sich schonmal.

Macht ihr das für den Fall in dem ihr den kompletten CmdLine der ersten nstanz übergibt oder einzelne Messages für jeden ParamStr?
Ich frage deshalb weil ich mir nicht sicher bin ob es sinnvoll / unproblematisch ist mehrere SendMessages aufzurufen (den Benutzer kann ja nichts davon abhalten eine zweite Instanz mit 10'000 Dateien als Parameter aufzurufen).
Bei CmdLine müsste der eigene Code die einzelnen Parameter aussortieren (Leerzeichenbehandlung, mal Anführungszeichen, mal nicht etc.)

himitsu 3. Jan 2017 12:10

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
MSDN-Library durchsuchenGetCommandLine
Aber leider ist Borland/Embarcadero so nett und stellt den Code zum Parsen nicht öffentlich bereit, womit du das dann selber zerlegen musst.

a.def 3. Jan 2017 12:20

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Zitat:

Zitat von Friday (Beitrag 1357899)
Macht ihr das für den Fall in dem ihr den kompletten CmdLine der ersten nstanz übergibt oder einzelne Messages für jeden ParamStr?)

Ich mache es so, dass ich alle ParamStr's getrennt durch irgendein spezielles Zeichen aneinanderklebe und es im Empfänger wieder auseinander pflücke.

Friday 3. Jan 2017 14:03

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
ja so hatte ich mir das auch schon gedacht, so werde ich es wohl auch tun.
Danke

a.def 3. Jan 2017 16:50

AW: Datei per Doppelklick dem bereits geöffneten Programm übergeben
 
Edit: da du XE3 hier, hier noch viel einfacher:
Delphi-Quellcode:
var
 aArr: TArray<string>;
 sStr: string;
begin
 sStr:= 'a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z';
 aArr := sStr.Split([':']);
end;
Das ist auch deutlich schneller als die erste Funktion da unten und viel weniger aufwendig zu implementieren als die zweite Funktion da unten.


Das hier könnte ich eventuell interessieren (Explode-Funktion): http://www.delphipraxis.net/3471-ein...-erzeugen.html


Es gibt auch eine schnellere Version, die Implementierung ist aber deutlich unschöner finde ich. Und diese schnellere Version lohnt sich auch nur, wenn es auf die Millisekunde genau ankommt.
Ich habe mal einen Test gemacht und 50.000x einen String und eine Zahl getrennt durch irgendein Zeichen an eine andere Exe geschickt die das dann mit Explode aufbohrt und aufwertet.
Das funktioniert wunderbar und ist schnell genug.

Wer trotzdem jede Millisekunde zählen will:
http://www.delphipraxis.net/82268-[optimiert]-explode-prozedur-reloaded-ersatz-fuer-codelib.html


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