Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi CreateProcess und anschließend WM_COPYDATA (https://www.delphipraxis.net/130178-createprocess-und-anschliessend-wm_copydata.html)

hirsch 4. Mär 2009 15:45


CreateProcess und anschließend WM_COPYDATA
 
Ich hoffe dass ich hier richtig bin.
Ich starte aus einem Programm heraus mit CreateProcess ein anderes Programm.
Wenn der Handle da ist, übergebe ich mit WM_CopyDATA einen String.
Das neu gestartete Programm empfängt den String und tut so manche Dinge damit.
Mein Problem ist, dass wenn der Handle schon vorhanden ist, ist das neu aufgerufene Programm noch nicht in der Lage den zu empfangenden String entgegenzunehmen. Also mein SendMessage geht an dem gestarteten Programm vorbei (kommt nicht an).
Wenn ich nun, nachdem das andere Programm gestartet ist nochmals den SendMessage mache, dann funktionierts.
Delphi-Quellcode:
procedure TFormMain.KindProgrammClick(Sender: TObject);
var StartupInfo: TStartupInfo;
    ProcessInfo: TProcessInformation;
    s : string;
    h  : HWND;
    cds : TCopyDataStruct;
    n  : integer;
begin
     FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
     StartupInfo.cb := Sizeof(TStartupInfo);
   
     if CreateProcess(nil,               { Anwendungsname}
                   'KindProgramm.exe', { Parameter}
                   nil,                  { Security}
                   nil,                  { Security}
                   False,
                   NORMAL_PRIORITY_CLASS, { Priorität}
                   nil,                  { Environment}
                   {PVerzeichnis,}        { Verzeichnis}
                   'C:\MeinOrdner',      { Verzeichnis}
                   StartupInfo,
                   ProcessInfo) then
     begin
          h:=FindWindow(nil,Pchar('KindProgramm'));
     end
     else
         Showmessage('Fehler! Programm KindProgramm.EXE ins Verzeichnis C:\MeinOrdner !');
     h:=FindWindow(nil,Pchar('KindProgramm.exe'));
     repeat //Warten bis Empfänger geöffnet und empfangsbereit ist
            h:=FindWindow(nil,PChar('KindProgramm'));
            StatusBar1.SimpleText:='Bitte warten!!!';
     until h<>0;

     begin // Empfänger-Fenster gefunden -> Daten senden
            cds.dwData:=0;
            cds.cbData:=StrLen(PChar(s)); //Length(s);
            cds.lpData:=PChar(s);
            SendMessage(h,WM_COPYDATA,Longint(Handle),Longint(@cds)); //<- kommt nicht an, erst beim zweiten Aufruf
     end;
end;
Wo mache ich den Denkfehler?

sirius 4. Mär 2009 15:59

Re: CreateProcess und anschließend WM_COPYDATA
 
Du hast hier wahrscheinlich Laufzeitprobleme. Die MEssagequeue ist evtl. nocht nicht fertig angelegt etc. pp.

Warum übergibst du das nicht direct bei CreateProcess im Parameter?

hirsch 4. Mär 2009 16:15

Re: CreateProcess und anschließend WM_COPYDATA
 
Hallo sirius,

gibt es eine Möglichkeit die Laufzeitprobs in den Griff zu bekommen?
Ich übergebe es nicht per Parameter, weil wenn ich im Vaterprogramm eine Eingabe mache, muss das Kindprogramm das übergeben bekommen..
Per Parameter wäre ja nur beim Öffnen einmalig....
oder?

sirius 4. Mär 2009 16:18

Re: CreateProcess und anschließend WM_COPYDATA
 
Dann übergib im Parameter das Handle o.ä. eines deiner Fenster. Und wenn dein Kindprogramm fertig ist mit dem Aufbau, schickt es eine "Hallo da bin ich Message" mit den Absenderdaten an dein Programm. Und dann kannst du die Absenderdaten dazu nutzen dein eigenes Zeugs zu versenden.
Damit entfällt das mühselige Findwindow.

Apollonius 4. Mär 2009 17:05

Re: CreateProcess und anschließend WM_COPYDATA
 
Du kannst MSDN-Library durchsuchenWaitForInputIdle verwenden, um auf das Ende der Initialisierung zu warten.

hirsch 5. Mär 2009 08:41

Re: CreateProcess und anschließend WM_COPYDATA
 
@ Apollonius
WaitForInputIdle hab ich probiert.
Sehr seltsam das verhalten, kann man kaum in Worte fassen...
Ich versuchs mal.
Delphi-Quellcode:
     
     h:=FindWindow(nil,'KindProgramm');
     repeat //Warten bis Empfänger geöffnet und empfangsbereit ist
            h:=FindWindow(nil,'KindProgramm');
            StatusBar1.SimpleText:='Bitte warten!!!';
     until h<>0;
     StatusBar1.SimpleText:='gefunden, warten bis eingabebereit ist';
     xc:=WaitForInputIdle(h,300000); //30Sec
     showmessage(intToStr(xc));
dann kommt der Sendmessage-Part im Listing.

Was passiert an der Oberfläche ->
'Bitte warten' kommt als erstes in die StatusBar, dann kommt 'gefunden, warten bis eingabebereit ist'
dann vergehen 30Sec. Vom Kindprogramm ist bis dahin nix zu sehen. 30sec lang... tze
Nach 30 sec kommt das Kindprogi vor das Vaterprogi.
Dann kommt das Showmessage mit der Zahl '4GB' in dezimal, logo.
Das klicke ich weg, dann kommt die SendMessage, die am Kindprogi wieder vorbei geht.
Ich blicks bald gar nimmer....


@ sirius
Das werde ich jetzt mal tun:
Im Kindprogi mal zurückübergeben, dann im Vaterprogi auswerten.
Ist vielleicht ganz geschickt, denn dann kann ich Status auch hin und her schieben...

Garfield 5. Mär 2009 11:18

Re: CreateProcess und anschließend WM_COPYDATA
 
Wie wäre es damit?
Delphi-Quellcode:
procedure TFormMain.KindProgrammClick(Sender: TObject);
var StartupInfo: TStartupInfo;
    ProcessInfo: TProcessInformation;
    s : string;
    h  : HWND;
    cds : TCopyDataStruct;
    n  : integer;
begin
     FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
     StartupInfo.cb := Sizeof(TStartupInfo);
   
     if CreateProcess(nil,               { Anwendungsname}
                   'KindProgramm.exe', { Parameter}
                   nil,                  { Security}
                   nil,                  { Security}
                   False,
                   NORMAL_PRIORITY_CLASS, { Priorität}
                   nil,                  { Environment}
                   {PVerzeichnis,}        { Verzeichnis}
                   'C:\MeinOrdner',      { Verzeichnis}
                   StartupInfo,
                   ProcessInfo) then
     begin
       StatusBar1.SimpleText:='Bitte warten!!!';
       WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
       ...

hirsch 5. Mär 2009 12:46

Re: CreateProcess und anschließend WM_COPYDATA
 
Vielen Dank @Garfield,
Das
Zitat:

WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
habe ich eingefügt, hat aber nix gebracht oder verändert.
Hab das jetzt so stehen:
Delphi-Quellcode:
procedure TFormMain.KindProgrammClick(Sender: TObject);
var StartupInfo: TStartupInfo;
    ProcessInfo: TProcessInformation;
    s : string;
    xc : cardinal;
    h : THandle;
    //h  : HWND;
    cds : TCopyDataStruct;
   

begin
     FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
     StartupInfo.cb := Sizeof(TStartupInfo);
     //StrPCopy(PVerzeichnis,LW_Char+':\MeinOrdner');
     if CreateProcess(nil,               { Anwendungsname}
                   'KindProgramm.exe', { Parameter}
                   nil,                  { Security}
                   nil,                  { Security}
                   False,
                   NORMAL_PRIORITY_CLASS, { Priorität}
                   nil,                  { Environment}
                   {PVerzeichnis,}        { Verzeichnis}
                   'MeinOrdner',         { Verzeichnis}
                   StartupInfo,
                   ProcessInfo) then
     begin
         //showmessage ('Gestartet');
     end
     else
         Showmessage('Fehler! Programm KindProgramm.EXE ins Verzeichnis C:\MeinOrdner !');
     StatusBar1.SimpleText:='gefunden, warten bis eingabebereit ist';
     WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
     repeat //Warten bis Empfänger geöffnet und empfangsbereit ist
            h:=FindWindow(nil,'KindProgramm');
            StatusBar1.SimpleText:='Bitte warten!!!';
     until h<>0;
     
     cds.dwData:=0;
     cds.cbData:=Length(s);
     cds.lpData:=PChar(s);
     SendMessage(h,WM_COPYDATA,integer(H),integer(@cds));
     xc:=GetlastError;
     if xc<>0 then
     begin
       SendMessage(h,WM_COPYDATA,integer(H),integer(@cds));
     end;
  end;
end;
Das habe ich nun ein paar mal getestet und das funktioniert soweit.
Aber ich denke die Lösung ist quick and dirty.
Den Denkfehler den ich mache hab ich nur umgangen, aber nicht behoben oder?


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