Jump to content
dummzeuch

Passing back a string from an external program

Recommended Posts

I have got two programs, both written in Delphi using the VCL. Program1 excecutes Program2 using CreateProcess, passing some parameters. In some circumstances I would like Program2 to return a string to Program1.

 

Since CreateProcess only returns an exit code, which is a number, this requires some additional communication.

 

Converting program2 into a DLL or Package is not an option in this case, neither is integrating the source code of program2 to program1.

 

The simplest way would probably be that program1 passes a file name to program2, program2 creates that file, writes the string to it and exits.

 

It could of course be implemented much more complicated, e.g. via sockets, Windows Messages, Shared Memory or even WriteProcessMemory.

 

Have you done something like this? If yes, which method did you use and what was your experience?

 

 

Share this post


Link to post
1 hour ago, Микола Петрівський said:

Just create global atom and pass it's code to the caller. Or caller can create empty atom, and then check for changes.

From the description it looks to me that atoms are immutable. So how do you propose to return a string from program2 to program1 via a global atom?

Share this post


Link to post

I would like to remind you that I was asking for experience with the IPC methods:

3 hours ago, dummzeuch said:

Have you done something like this? If yes, which method did you use and what was your experience?

For now I have implemented it with passing a file name as described in my original post. Does this have any drawbacks (apart from the obvisous one:

It creates a race condition.

I have mitigated this for now by creating a unique temporary directory to place the file in.

Share this post


Link to post
4 hours ago, dummzeuch said:

I have got two programs, both written in Delphi using the VCL. Program1 excecutes Program2 using CreateProcess, passing some parameters. In some circumstances I would like Program2 to return a string to Program1.

 

Since CreateProcess only returns an exit code, which is a number, this requires some additional communication.

 

Converting program2 into a DLL or Package is not an option in this case, neither is integrating the source code of program2 to program1.

 

The simplest way would probably be that program1 passes a file name to program2, program2 creates that file, writes the string to it and exits.

 

It could of course be implemented much more complicated, e.g. via sockets, Windows Messages, Shared Memory or even WriteProcessMemory.

 

Have you done something like this? If yes, which method did you use and what was your experience?

 

 

A fairly simple method is to pass a window handle to program2 on the command line an then have that program sent its result back in a WM_COPYDATA message to that window. Only caveat: program1 must not wait on program2 to finish in a manner that blocks message processing of the main thread.

  • Like 2

Share this post


Link to post
1 hour ago, dummzeuch said:

It creates a race condition

I don't understand the 'race condition'?

 

I mean you are doing the most basic of all communications, execute an app, wait for it to exit and read the output file.
In one form or another we do this every day 🙂

 

But since you are fishing for experience, I use this as part of a self updating feature.

  1. Get a Temp filename from the OS
  2. Write some data to it
  3. Execute another app waiting for it to complete
  4. Read any Error code it may have added to the file
  5. Delete the file

Other than the New feature where a user can add the Temp folder to the 'Controlled Folder Access' Ransomware Protection this is as basic as it gets.

Share this post


Link to post
19 minutes ago, FredS said:

I don't understand the 'race condition'?

If there are multiple instances of program1 and it always uses the same file name when it starts its own instance of program2. These multiple instances would then all write to the same file.

That's a race condition in my opinion.

Share this post


Link to post
1 minute ago, dummzeuch said:

always uses the same file name

 

OK, getting a temp filename from the OS solves that.

Share this post


Link to post
 
 
 
19 hours ago, dummzeuch said:

If there are multiple instances of program1 and it always uses the same file name when it starts its own instance of program2. These multiple instances would then all write to the same file.

That's a race condition in my opinion.

I'd call that a concurrency issue, rather than a race condition?

SharedFileName := '%temp%\MyFileName.ext.' + GetCurrentProcessId.ToString;

Share this post


Link to post

Depends on the dictionary, I guess.

Race conditions rarely flag as errors, but cause inconsistent or erratic data, possibly leading to wrongful processing later on.

In this case, at least one of the four parties would be denied access (due to exclusive write lock and - depending on the programmmer - exclusive read) to the file and hence should have/raise awareness of a problem. 

But, whatever.

Share this post


Link to post
1 hour ago, Lars Fosdal said:

Depends on the dictionary, I guess.

Race conditions rarely flag as errors, but cause inconsistent or erratic data, possibly leading to wrongful processing later on.

In this case, at least one of the four parties would be denied access (due to exclusive write lock and - depending on the programmmer - exclusive read) to the file and hence should have/raise awareness of a problem. 

But, whatever.

Well, there are plenty of types for which races lead to errors. But how races manifest is not part of what defines them. A race is simply unserialised access to a shared resource. There aren't multiple definitions of this term. 

Share this post


Link to post

Dear Dummzeuch,

Try Add-in A-Tools: Query, Share Excel file on LAN, internet with multiple users.

See more details at  http://www.atoolspro.com/

You can download at http://bluesofts.net/Download/phan-mem/phan-mem-mien-phi.html

Try it and find out how it works, as it describes you looking for a solution to your need solve?

It's in-process-server (file AddinATools.dll), programmed in delphi language.

Best Regards!

Share this post


Link to post
2 hours ago, LCAO-MO said:

It's in-process-server (file AddinATools.dll), programmed in delphi language.

Thanks for the suggestion, but that sounds like quite some overkill for my purpose.

Share this post


Link to post

To answer your question, yes, I have done exactly this.  But in my case program 1 was guaranteed to be a singleton on the machine, so I could just create an empty registry key before invoking program 2 and have program 2 place the result there.  If you have control over the number of instances of your program 1 you might be able to adapt this solution.  It has the advantages of extreme simplicity and needing no extra tools or special functions.

  • Thanks 1

Share this post


Link to post

Why inventing bicycles with triangular wheels when writing to STDOUT is a very simple method proven by decades? All *nix ecosystem is built on this mechanism.

Executed app won't need anything more than WriteLn and executor app will have to intercept pipe handles.

  • Like 1
  • Haha 1

Share this post


Link to post
On 8/8/2019 at 3:59 AM, Fr0sT.Brutal said:

Why inventing bicycles with triangular wheels when writing to STDOUT is a very simple method proven by decades? All *nix ecosystem is built on this mechanism.

Executed app won't need anything more than WriteLn and executor app will have to intercept pipe handles.

Thank you; I'm reading this on a Linux box and thought I was missing something for a second. "Write programs to handle text streams, because that is a universal interface." - Peter H. Salus,  "A Quarter-Century of Unix"

Now, the question is how to handle this with Delphi... Delphi has never gained a simple solution for calling programs and getting the text results back, which is a weird and glaring omission in my mind. FreePascal has a handful of routines for doing so (some of which work across platforms), Qt has QProcess, etc.

 

There's some information here on FreePascal's TProcess:

 

https://wiki.freepascal.org/TProcess

 

and there's a port of TProcess to Delphi (which I haven't tried):

 

https://github.com/z505/TProcess-Delphi

 

Otherwise, you're left with the somewhat complicated default Delphi way of doing this....

 

https://stackoverflow.com/questions/9119999/getting-output-from-a-shell-dos-app-into-a-delphi-app

  • Like 1

Share this post


Link to post
Posted (edited)
On 6/13/2019 at 12:02 PM, dummzeuch said:

Windows Messages

Windows Messages is not complicated: Pass the window handle of Program1 as a parameter to Program2 which then sends the string back to Program1 as a Windows Message.

 

Or - if Program2 is a console type program: Simply (programmatically) read the console output of Program2.

Edited by PeterPanettone

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×