Run a java Jar by Delphi

Asked

Viewed 2,442 times

4

I wonder if there is a way to execute a jar by Delphi and give commands to it as if it were a command line.

The truth is that I have a java application that no longer has access to the code and it is limited to two commands via console, I would like to create an application in Delphi that could by a graphical interface control this jar and give commands to them, then instead of the user typing the commands, he would click on buttons and Delphi would do the rest.

Is there any way to do that?

  • At least until Delphi 7 this was done using the Windows API. If you just want to launch the other application is easy. If you want to wait for him to finish, it’s more boring and if you want to read his exits you have to go to the dark side of the force. Specify your version of Delphi and what you need to get from the other program. You can read this in the meantime: Delphi.about.com/od/windowsshellapi/a/executeprogram.htm

  • Exactly @Caffé, I want to run and read their outputs and give entries in it too, in the gringo overflow stack told me something about Createprocess and about Pipes but I did not understand very well how it works and if it will work for my case, as for the version of Delphi I have here available to 2009 and XE5

  • 1

    In a very simple way, you can use java seuJar.jar parametros > .\output.txt and then the console output will be saved in the informed file.

  • The @Caputo is correct if you don’t need to get the outputs whereas they are delivered. Also, I have a code ready that I adapted from an article on the internet that I can’t find anymore. I’ll see if I bring it tomorrow to post here. Now, as for sending entries to a running application the solution can be very complex and depends on a lot of things: do you pass values just by firing the program? (then it would be simple). Do you want to pass values while running the program? What kind of values are and how the program expects to get these values?

  • So @Caffé, the application that I have it has only 2 commands, list and exit, I would need to open this application by Delphi and the same give these commands and in case of the list I would get the information that it would return.

  • @brunodotcom Managed to solve the problem?

  • 1

    @qmechanik Thanks for the answers, I haven’t really had time to implement your idea, but apparently it will. By the time I can deploy I’ll have the answer here.

Show 2 more comments

2 answers

5

Assuming that your app jar be called meuApp.jar you can do it this way

in Delphi vc executes the command with Winexec for example, or Shellexecute

WinExec('java c:\path\para\meuApp.jar listar >> .\resultadoLista.txt', SW_HIDE);

or

ShellExecute(handle,'open',PChar('java'), 
  'c:\path\para\meuApp.jar listar >> .\resultadoLista.txt','',SW_HIDE)

Then in Delphi you can load the result using a memo or stringlist for example:

StringList.LoadFromFile('.\resultadoLista.txt')

4

In addition to manners cited by Caputo, it is possible to use the function ShellExecuteEx to execute the jar, save to a file and upload it to a TStringList. Something like this:

function ExecutarComando(Comando: string): TStringList;
var
 SE: TShellExecuteInfo;
 ExitCode: DWORD;
begin
 Result := TStringList.Create;
 FillChar(SE, SizeOf(SE), 0);
 SE.cbSize := SizeOf(TShellExecuteInfo);
 SE.fMask := SEE_MASK_NOCLOSEPROCESS;
 SE.Wnd := Application.Handle;
 SE.lpFile := 'cmd.exe';
 SE.lpParameters :=  pchar('/C' + Comando + ' > output.txt');
 SE.nShow := SW_HIDE;

 if ShellExecuteEx(@SE) then begin
   repeat
     Application.ProcessMessages;
     GetExitCodeProcess(SE.hProcess, ExitCode);
   until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
     Result.LoadFromFile('output.txt');
 end else
     RaiseLastOSError;
end;

To use:

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines := ExecutarComando('java arquivo.jar listar');
end;

The above method is functional, but not ideal, another way more elegant to do this is to create the process with the function CreateProcess, and redirect the output to a Buffer with the function CreatePipe, basically.

That page shows an example of how to do this.

function GetDosOutput(CMD: string; Diretorio: string = 'C:\'): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  Handle, WasOK: Boolean;
  Buffer: array[0..255] of AnsiChar;
  BytesRead: Cardinal;
begin
  Result := '';
  SA.nLength := SizeOf(SA);
  SA.bInheritHandle := True;
  SA.lpSecurityDescriptor := nil;
  CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);

  try
     FillChar(SI, SizeOf(SI), 0);
     SI.cb := SizeOf(SI);
     SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
     SI.wShowWindow := SW_HIDE;
     SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
     SI.hStdOutput := StdOutPipeWrite;
     SI.hStdError := StdOutPipeWrite;

     Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CMD), nil, nil, True,
     0, nil, pchar(Diretorio), SI, PI);
     CloseHandle(StdOutPipeWrite);
     if Handle then
       try
         repeat
           WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
           if BytesRead > 0 then begin
             Buffer[BytesRead] := #0;
             Result := Result + String(Buffer);
           end;
         until not WasOK or (BytesRead = 0);
        WaitForSingleObject(PI.hProcess, INFINITE);
       finally
         CloseHandle(PI.hThread);
         CloseHandle(PI.hProcess);
       end;
   finally
     CloseHandle(StdOutPipeRead);
   end;
end;

To use:

procedure TForm1.Button2Click(Sender: TObject);
begin
// O segundo argumento é opcional, por padrão o comando executa em C:\
Memo1.Text := GetDosOutput('java arquivo.jar listar', 'C:\Dir\'); 
end;
  • Regarding the ShellExecuteEX, when the mask SEE_MASK_NOCLOSEPROCESS is used, the caller is responsible for closing the Handle he received. In your case, you forgot to close the Handle hProcess.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.