Joseph MItzen 251 Posted August 18, 2019 2 hours ago, PeterPanettone said: Or - if Program2 is a console type program: Simply (programmatically) read the console output of Program2. It's not so simple in Delphi though. Share this post Link to post
David Heffernan 2345 Posted August 18, 2019 1 hour ago, Joseph MItzen said: It's not so simple in Delphi though. It really is 1 Share this post Link to post
aehimself 396 Posted August 29, 2019 I always used this code, which works fine. The only issue is if the other application is expecting an input (even a keypress to finish) because ReadFile will wait endlessly as far as I recall. It is easy to finetune it though. function GetDosOutput(CommandLine: string; var ReturnString: String; var ReturnCode: Cardinal): Boolean; const LOGON_WITH_PROFILE = $00000001; var SA: TSecurityAttributes; SI: TStartupInfo; PI: TProcessInformation; StdOutPipeRead, StdOutPipeWrite: THandle; WasOK: Boolean; Buffer: array[0..255] of AnsiChar; BytesRead: Cardinal; WorkDir: string; Handle: Boolean; begin Handle := False; ReturnCode := 255; Result := False; ReturnString := ''; SA.nLength := SizeOf(SA); SA.bInheritHandle := True; SA.lpSecurityDescriptor := nil; CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); Try With SI Do Begin FillChar(SI, SizeOf(SI), 0); cb := SizeOf(SI); dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; wShowWindow := SW_HIDE; //wShowWindow := SW_MINIMIZE; hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin hStdOutput := StdOutPipeWrite; hStdError := StdOutPipeWrite; End; WorkDir := '.'; Handle := CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_PROCESS_GROUP or CREATE_NEW_CONSOLE, nil, PChar(WorkDir), SI, PI); CloseHandle(StdOutPipeWrite); If Handle Then Try Repeat WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); If BytesRead > 0 Then Begin Buffer[BytesRead] := #0; ReturnString := ReturnString + Buffer; End; Until Not WasOK Or (BytesRead = 0); WaitForSingleObject(PI.hProcess, INFINITE); GetExitCodeProcess(PI.hProcess, ReturnCode); While (Length(ReturnString)<>0) And ((ReturnString[Length(ReturnString)]=#10) Or (ReturnString[Length(ReturnString)]=#13)) Do Delete(ReturnString,Length(ReturnString),1); Result := True; Finally CloseHandle(PI.hThread); CloseHandle(PI.hProcess); End; Finally CloseHandle(StdOutPipeRead); End; end; 2 Share this post Link to post
Mahdi Safsafi 225 Posted August 30, 2019 Quote Converting program2 into a DLL or Package is not an option in this case, neither is integrating the source code of program2 to program1. You don't need to convert Program2 into DLL. Just exports your functions and consume them directly from Program1 (just like DLL). // ========================================== Program1 ========================================== program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; const Program2 = 'Project2.exe'; type TGetProgram2Result = function(Param1, Param2: Integer): string; var LIB: HMODULE; GetProgram2Result: TGetProgram2Result = nil; s: string = ''; begin try LIB := LoadLibrary(Program2); @GetProgram2Result := GetProcAddress(LIB, 'GetProgram2Result'); s := GetProgram2Result(5, 2); Writeln(s); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. // ========================================== Program2 ========================================== program Project2; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; function GetProgram2Result(Param1, Param2: Integer): string; begin Result := Format('%d+%d=%d', [Param1, Param2, Param1 + Param2]); end; // ------------- EXPORTS ------------- exports GetProgram2Result; begin try Writeln('This is Program2'); Writeln(GetProgram2Result(5, 2)); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Share this post Link to post
David Heffernan 2345 Posted August 30, 2019 34 minutes ago, Mahdi Safsafi said: You don't need to convert Program2 into DLL. Just exports your functions and consume them directly from Program1 (just like DLL). // ========================================== Program1 ========================================== program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; const Program2 = 'Project2.exe'; type TGetProgram2Result = function(Param1, Param2: Integer): string; var LIB: HMODULE; GetProgram2Result: TGetProgram2Result = nil; s: string = ''; begin try LIB := LoadLibrary(Program2); @GetProgram2Result := GetProcAddress(LIB, 'GetProgram2Result'); s := GetProgram2Result(5, 2); Writeln(s); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. // ========================================== Program2 ========================================== program Project2; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; function GetProgram2Result(Param1, Param2: Integer): string; begin Result := Format('%d+%d=%d', [Param1, Param2, Param1 + Param2]); end; // ------------- EXPORTS ------------- exports GetProgram2Result; begin try Writeln('This is Program2'); Writeln(GetProgram2Result(5, 2)); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Nope, that doesn't work. You can't expect to load an exe file with LoadLibrary. Also, even if you could, don't go exporting string across a module boundary. I'm astounded at all the posting here for a trivial problem with a standard solution. Share this post Link to post
Mahdi Safsafi 225 Posted August 30, 2019 @David Heffernan Quote Nope, that doesn't work. You can't expect to load an exe file with LoadLibrary. Also, even if you could, don't go exporting string across a module boundary. You can use LoadLibrary with exe file ! The only things is that you need to keep an eye on initialisation. Share this post Link to post
David Heffernan 2345 Posted August 30, 2019 6 minutes ago, Mahdi Safsafi said: @David Heffernan You can use LoadLibrary with exe file ! The only things is that you need to keep an eye on initialisation. No. Because there is no DllMain and so nothing is initialized. And then there are the lack of relocations. What's wrong with Delphi programmers. Read the standard output already! Share this post Link to post