Recent

Author Topic: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?  (Read 4018 times)

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1311
    • Lebeau Software
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #30 on: March 31, 2023, 10:14:12 pm »
Now I do print more it results to find target is okay but nothing happen on 64bit.

This is a known issue in FreePascal/Lazarus (oh yeah, now I remember this.  I did know this once, but forgot about it):

SendMessage WM_COPYDATA is not recognized by Program

SengMessage WM_COPYDATA . Target doesn't receive anything

Basically, the LCL does not dispatch WM_COPYDATA for the Form class to receive, like Delphi's VCL does. So, the solution is to manually subclass the Form's window directly, using the Win32 API SetWindowLong/Ptr() or SetWindowSubclass() function, per MSDN: Subclassing Controls.

This is also documented in the Lazarus Wiki:
Processing non-user messages in your window.

The 2nd forum link above has code to demonstrate how to do this.
« Last Edit: March 31, 2023, 11:43:25 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #31 on: March 31, 2023, 10:59:58 pm »
attached is a test app where I made a Unit that can add messages to the loop so you can implement the message handler in the class.

The only true wisdom is knowing you know nothing

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2006
  • Fifty shades of code.
    • Delphi & FreePascal
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #32 on: March 31, 2023, 11:11:59 pm »
Now I do print more it results to find target is okay but nothing happen on 64bit.

This is a known issue in FreePascal/Lazarus (oh yeah, now I remember this.  I did know this once, but forgot about it):

SendMessage WM_COPYDATA is not recognized by Program

SengMessage WM_COPYDATA . Target doesn't receive anything

The solution is to manually subclass the receiving window, using the Win32 API SetWindowLong/Ptr() or SetWindowSubclass() function, per MSDN: Subclassing Controls.  This is also documented in the Lazarus Wiki: Processing non-user messages in your window. The 2nd forum link above has code to demonstrate how to do this.
:D :D :D and I thought I am somewhere doing wrong, I've now read more about that scenario here
Thank you Remy!
I will try later again with custom WndProc but since LCL refuse that message I think WM_COPYDATA is a bad choice than for doing IPC with Lazarus.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2006
  • Fifty shades of code.
    • Delphi & FreePascal
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #33 on: April 01, 2023, 12:41:55 am »
Okay.... custom WndProc did not worked for me, message again was eaten before it could be processed but subclassing worked good.
Attached a working version between Delphi 32 bit and Lazarus 64 bit.
Replacing FindWindow() is a very good advise, in that release it still uses it but more restricted by using both arguments.
Thank you Remy for your advises!
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

tetrastes

  • Sr. Member
  • ****
  • Posts: 469
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #34 on: April 01, 2023, 12:48:40 am »
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2006
  • Fifty shades of code.
    • Delphi & FreePascal
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #35 on: April 01, 2023, 12:57:54 am »
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

tetrastes

  • Sr. Member
  • ****
  • Posts: 469
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #36 on: April 01, 2023, 01:18:26 am »
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)

It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2006
  • Fifty shades of code.
    • Delphi & FreePascal
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #37 on: April 01, 2023, 01:33:39 am »
It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.
No no, everything is okay with the bitness, that issue rely on the way the FPC/Lazarus developers decided to support Windows specific messages (they just don't :D)
Your contribution was not helping me but at least somewhere in the Examples is written that only LM_USER+ messages are supported and the rest gets eaten, even that they decided to include the message consts in the Windows unit.
After searching for that kind of issue in combination with FPC/Lazarus I really do not want to start flaming or anything else in that direction.
It is like it is and I am thankful for the help I do get here from the pro's :-*
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

tetrastes

  • Sr. Member
  • ****
  • Posts: 469
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #38 on: April 01, 2023, 01:47:25 am »
It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.
No no, everything is okay with the bitness, that issue rely on the way the FPC/Lazarus developers decided to support Windows specific messages (they just don't :D)

I understand this, it is simply quote from your post.

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #39 on: April 01, 2023, 10:30:03 am »
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)
Being the tread creator (OP) I do not see how the project you posted can help me at all...
In what way shall it be used? There is only one program in the zipfile and it is also not Delphi7 compatible, complains about a number of properties in the memo when loaded into Delphi7.
What version of Delphi (32 bit) do you use?

There should be two applications for my use case at least:
- One main Lazarus64 bit GUI application (the client), which needs information from the server.
- One Delphi7 32 bit non-GUI server application (invisible), which waits for incoming requests, reads the request and performs the needed action and then sends back a result.

My use case is:

1) A Lazarus 64 bit application, which needs to read from a USB connected device using a driver from the manufacturer.
But the mfg supplied SDK for Delphi does not work with Lazarus because the interface (an OBJ file) is not a COFF formated obj, which is the only type it seems like the FreePascal linker can read.

2) So I need to use a helper app written for Delphi7, which can read the USB and supply the data to the main Lazarus app.
This app needs to be able to receive commands from the main app on what to read from USB and then read and send back the result.

So there are two apps involved, one Delphi7 32 bit server console app and one Lazarus 64 bit main GUI app.

The discussion in this thread is about getting IPC between them working but the GitHub IPC examples I have been pointed to do not even work with both being Lazarus apps (the server crashes immediately on start).

So NO I am not happy.....   >:(

Do I really have to make a network based server app using an Indy10 socket client/server pair?

---- EDIT -----
I have come to the conclusion that using TCP/IP sockets to communicate between the two apps is probably the better solution after all. At least if I will save myself from pulling my hair out...
I could probably limit the server to only listen on localhost so no external spying will be possible.

« Last Edit: April 01, 2023, 10:57:41 am by BosseB »
--
Bo Berglund
Sweden

alpine

  • Hero Member
  • *****
  • Posts: 1032
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #40 on: April 01, 2023, 11:51:35 am »
*snip*

My use case is:

1) A Lazarus 64 bit application, which needs to read from a USB connected device using a driver from the manufacturer.
But the mfg supplied SDK for Delphi does not work with Lazarus because the interface (an OBJ file) is not a COFF formated obj, which is the only type it seems like the FreePascal linker can read.

2) So I need to use a helper app written for Delphi7, which can read the USB and supply the data to the main Lazarus app.
This app needs to be able to receive commands from the main app on what to read from USB and then read and send back the result.

So there are two apps involved, one Delphi7 32 bit server console app and one Lazarus 64 bit main GUI app.

*snip*
What if you just write a simple console Delphi7 app, give the commands as a parameter and use its console output as the result?
You can even use the TProcess.Input/Output pipe streams for communicating while dealing only with ReadLn/WriteLn into the Delphi program.
https://wiki.freepascal.org/Executing_External_Programs#How_to_redirect_output_with_TProcess
 
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2006
  • Fifty shades of code.
    • Delphi & FreePascal
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #41 on: April 01, 2023, 11:54:59 am »
There is only one program in the zipfile and it is also not Delphi7 compatible, complains about a number of properties in the memo when loaded into Delphi7.
What version of Delphi (32 bit) do you use?
I just downloaded my own Zip and on my machine it shows me
WM_COPYDATA\Delphi32\Demo32.dpr = That file you need to open in your version of Delphi
WM_COPYDATA\Lazarus64\Demo64.lpi = That file you need to open in your version of Lazarus
So you have two complete project sources for two different Pascal environments.

I did coded by using my oldest available Delphi, Turbo Delphi 2006 and a current version of Lazarus(Trunk)/FreePascal(Stable)

complains about a number of properties in the memo when loaded into Delphi7.
Since you are very detailed I can not help further.

From my side you got two different working IPC concepts with full sources, don't expect more from me.
MemoryMappedFile and WM_COPYDATA and all I see from you is, GitHub IPC DLL errors.

Best wishes!
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #42 on: April 01, 2023, 02:46:07 pm »
Do I really have to make a network based server app using an Indy10 socket client/server pair?

and

---- EDIT -----
I have come to the conclusion that using TCP/IP sockets to communicate between the two apps is probably the better solution after all. At least if I will save myself from pulling my hair out...
I could probably limit the server to only listen on localhost so no external spying will be possible.

I'm probably missing something but...

From your description, you will have a Delphi 7 process that communicates with a USB dongle.  That Delphi 7 process will read/write whatever data is protected by the dongle.  That program needs to provide and receive data from a 64 bit program written in FPC.  All this will take place on the _same_ machine.

If that description is reasonably accurate then implementing the communication between that server and any number of clients is a shoe-in for memory mapped files.  Using TCP/IP to implement such simple IPC is grossly inefficient.

I presume you already know how to write the server using Delphi 7 to read/write data and keep the USB dongle happy.  What left is to create a mechanism for that program to communicate with another (most likely using memory mapped files since that seems quite appropriate in this case) and write the 64 bit program that reads/writes the data.

did I miss something ?
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

alpine

  • Hero Member
  • *****
  • Posts: 1032
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #43 on: April 01, 2023, 10:05:37 pm »
@BosseB
Just to demonstrate how simple (and portable) it can be, consider the following example:

Delphi7 32 bit server console app
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. procedure ReadProc;
  7. var
  8.   StartAddr, EndAddr, W: Word;
  9. begin
  10.   ReadLn(StartAddr, EndAddr);
  11.   for W := StartAddr to EndAddr - 1 do
  12.     WriteLn(IntToHex({ActualRead(W)}0, 2));
  13.   WriteLn('.');
  14. end;
  15.  
  16. procedure WriteProc;
  17. var
  18.   Addr: Word;
  19.   Value: Byte;
  20. begin
  21.   ReadLn(Addr, Value);
  22.   //if not ActualWrite(Addr, Value) then
  23.   //  WriteLn('?');
  24.   //else
  25.     WriteLn('.');
  26. end;
  27.  
  28. var
  29.   Done: Boolean;
  30.   Cmd: String;
  31. begin
  32.   Done := False;
  33.   repeat
  34.     ReadLn(Cmd);
  35.     if Cmd = 'quit' then
  36.       Done := True
  37.     else if Cmd = 'read' then
  38.       ReadProc
  39.     else if Cmd = 'write' then
  40.       WriteProc
  41.     else
  42.       ;
  43.   until Done;
  44. end.
  45.  

And for Lazarus 64 bit main app:
Code: Pascal  [Select][+][-]
  1. program client;
  2.  
  3. uses
  4.   Classes, SysUtils, Process;
  5.  
  6. var
  7.   Srv: TProcess;
  8.   CRLF: String = LineEnding;
  9.   Cmd: String;
  10.  
  11. function GetCh: Char;
  12. begin
  13.   while Srv.Output.NumBytesAvailable < 1 do ;
  14.   Srv.Output.Read(Result, 1)
  15. end;
  16.  
  17. procedure EatChrs;
  18. begin
  19.   while Srv.Output.NumBytesAvailable > 0 do
  20.     GetCh;
  21. end;
  22.  
  23. procedure quitf;
  24. begin
  25.   Cmd := 'quit' + CRLF;
  26.   Srv.Input.Write(Cmd[1], Length(Cmd));
  27.   while Srv.Active do
  28.     Sleep(10);
  29. end;
  30.  
  31. procedure readf(StartAddr, EndAddr: Word);
  32. var
  33.   C: Char;
  34. begin
  35.   EatChrs;
  36.   Cmd := 'read' + CRLF + IntToStr(StartAddr) + ' ' + IntToStr(EndAddr) + CRLF;
  37.   Srv.Input.Write(Cmd[1], Length(Cmd));
  38.   repeat
  39.     C := GetCh;
  40.     Write(C); // process char instead of write -
  41.     //append it to a string and use e.g. ReadStr() or StrToInt() on CRLF
  42.   until C = '.';
  43. end;
  44.  
  45. function writef(StartAddr: Word; Value: Byte): Boolean;
  46. var
  47.   C: Char;
  48. begin
  49.   EatChrs;
  50.   Cmd := 'write' + CRLF + IntToStr(StartAddr) + ' ' + IntToStr(Value) + CRLF;
  51.   Srv.Input.Write(Cmd[1], Length(Cmd));
  52.   repeat
  53.     C := GetCh; Write(C);
  54.   until C in ['.', '?'];
  55.   Result := C = '.';
  56. end;
  57.  
  58. begin
  59.   Srv := TProcess.Create(Nil);
  60.   try
  61.    Srv.Executable := ExtractFilePath(ParamStr(0)) + 'project1.exe';
  62.    Srv.Options := Srv.Options + [poUsePipes];
  63.    Srv.Execute;
  64.  
  65.    readf(0, 10);
  66.    writef($1000, $AA);
  67.    quitf;
  68.  
  69.   finally
  70.     Srv.Free;
  71.   end;
  72. end.  

As you can see, there is no additional complications regarding bitness, object  formats, socket programming, specific APIs, etc. 

IMO that is the most natural way to do IPC - with pipes.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

af0815

  • Hero Member
  • *****
  • Posts: 1284
Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
« Reply #44 on: April 02, 2023, 08:35:40 am »
BTW, you can use for the server and clients the package Snap7. This is a very robust industrial communication system based on a industrial 'Standard' of a large PLC-Supplier and very well documented. You can have a lot of clients, and share information between mixed systems. Not only Delphi and Lazarus. This Package is available on nearly all popular systems and bitness. For the clients you can also use PascalSCADA, which works without a library and is pure pascal (but can not be a server, client only). PascalSCADA is also very robust, but i think the never versions are Lazarus/fpc only.

I know this idea is not mainstream working with sockets or something, but it is very very stable and used normal for industrial enviroments. But only a idea more for discussion..
 
regards
Andreas

 

TinyPortal © 2005-2018