pyscripter 788 Posted June 28 (edited) There are many components/libraries available for running processes and capturing their output. But, I got frustrated with their design and functionality, mostly for the following reasons: Fixation with and premature conversion to strings. Processes produce and consume bytes. Blocking reading of process output, resulting to inefficiencies (tight loops with Sleep, or separate threads for reading the output or providing input to the process) Incomplete features and/or over-bloated So, I have made my own pascal-process single unit library. Main features: Asynchronous reading of process output Separate stdout and stderr reading which can optionally be merged Ability to consume output as it is produced or else let it accumulate and read the final result Ability to provide input to the running process before or while the process is running. Ability to terminate the running process. Synchronous and asynchronous execution of processes. Interfaced-based facilitating memory management. MIT licence Usage: You do not need to install the library. Just download or clone the repo and add the source subdirectory to the Library path. Then add PascalProcess to your uses clause. If you just want to get the output of a process you can use the class functions of TPProcess. TPProcess = class(TInterfacedObject, IPProcess) class function Execute(const ACommandLine: string; const ACurrentDir: string = ''): TBytes; overload; class procedure Execute(const ACommandLine: string; const ACurrentDir: string; out Output, ErrOutput: TBytes) overload; end; This is an example: var Output: TBytes; begin Output := TPProcess.Execute('cmd /c echo Hi'); Writeln(TEncoding.ANSI.GetString(Output)); end; For more demanding cases you can use the IPProcess interface. Example: type TUtils = class class procedure OnRead(Sender: TObject; const Bytes: TBytes); end; class procedure TUtils.OnRead(Sender: TObject; const Bytes: TBytes); begin Writeln(TEncoding.ANSI.GetString(Bytes)); end; procedure Test2; // Processes ouput as it gets produced // The main thread terminates the process var Process: IPProcess; begin Process := TPProcess.Create('cmd /c dir c:\ /s'); Process.OnRead := TUtils.OnRead; WriteLn('Press Enter to start the process. Press Enter again to terminate'); ReadLn; Process.Execute; ReadLn; Process.Terminate; end; See here the definition of IPProcess. Limitations: Currently the library is Windows only. The intention is to support other platforms (help wanted). Edited June 28 by pyscripter 7 2 Share this post Link to post
Kas Ob. 145 Posted June 29 @pyscripter , nice ! Removing "([])" from https://github.com/pyscripter/pascal-process/blob/main/Source/PascalProcess.pas#L454-L455 will make it compile and run on XE8 Share this post Link to post
pyscripter 788 Posted June 29 (edited) 1 hour ago, Kas Ob. said: will make it compile and run on XE8 Done. Thanks. Edited June 29 by pyscripter Share this post Link to post
pyscripter 788 Posted 13 hours ago (edited) pascal-process is now multi-platform! So now there is a Delphi library to match fpc's TProcess. Desktop POSIX platforms (LINUX and MACOS) are now supported in addition to Windows. I have tested with LINUX. Since, I do not have a MACOS system available, I would appreciate some help in testing with MACOS. Edited 13 hours ago by pyscripter Share this post Link to post
Dave Nottage 620 Posted 12 hours ago 1 hour ago, pyscripter said: I would appreciate some help in testing with MACOS. I tested it on macOS using this command: "/Applications/PAServer-23.3.app/Contents/MacOS/iosinstall" -q -c -t 5 -W Which ran as expected. This is the command PAServer issues when it wants to detect what devices are visible to the Mac. One thing to note: in the docs on your repo, it suggests using this in the OnRead (of which the parameters in the example do not match the actual source): TEncoding.ANSI.GetString(Bytes) Which might work elsewhere, but on macOS this works: TEncoding.Default.GetString(Bytes) 1 Share this post Link to post
pyscripter 788 Posted 11 hours ago (edited) @Dave Nottage Thanks for testing. I have updated the Readme with the corrected parameter list for OnRead. Regarding the conversion to string, the whole point of the library is that you get bytes. It is up to the user to use the bytes whichever way is appropriate. The console encoding may be not be Delphi's default encoding. In Linux it is most likely UTF8. On Windows one might use the GetConsoleOutputCP API to get the code page for the output. However even that is not reliable, For instance, on Windows, the scp command expects input and produces output in UTF8 encoding irrespective of the console encoding. The use of ANSI encoding on the project page was just an example. I agree thought that for the example TEncoding.Default is a better choice. So I have updated that as well. Edited 10 hours ago by pyscripter Share this post Link to post
Kas Ob. 145 Posted 8 hours ago @pyscripter Hi, Are you up for suggestions ? even if they are not so small touching the core approach with overlapped operation (on Windows) ? Share this post Link to post