Check subprocess in implementation

Asked

Viewed 770 times

0

When my application starts I need to check if a third party program is running, if not, I need to start it.

The problem is that the program made in Java and when it is running it runs within Java itself, as in the image:

Programa rodando

How can I identify if the program is running? I’ve used some methods I found to check the processes running in windows only most just identify the process "javaw.exe" and I want to identify the Synchronizer Demander.

Obs.: I can’t search for the title of the window because it changes

Utilizo Delphi RAD Studio XE10.2 Berlin

  • Out of curiosity if you start the process even if it is already running will duplicate it?

  • No, it opens only once, when the process is already running a message is displayed saying that only one application can be opened at a time

  • Wait for an answer because I do not know Delphi, but if there is no viable solution can always do the opposite and capture this error.

2 answers

1

It is possible to search using the functions Process32first/Process32next windows, looping existing processes to search for the executable name for example. For your case you could initially do a search for Java, then make a second loop in the child processes (comparing the ID of the parent process), to check if your application is running.

Example:

uses
  TlHelp32, System.Generics.Collections;


function RetornaPID(exeFileName: string): integer;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  Result := -1;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  while Integer(ContinueLoop) <> 0 do
  begin
    if (UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =  UpperCase(ExeFileName))
    or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName)) then
    begin
      Result := FProcessEntry32.th32ProcessID;
      break;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

Function RetornaListaprocessosFilhos(aIDProcessoPai: Integer): TList<Integer>;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  Result := TList<Integer>.Create;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, aIDProcessoPai);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  while Integer(ContinueLoop) <> 0 do
  begin
    if FProcessEntry32.th32ParentProcessID = aIDProcessoPai then
    begin
      Result.add(FProcessEntry32.th32ProcessID);
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  vPIDPai: Integer;
  vPIDFilho: Integer;
  vListaProcessosFilhos: TList<Integer>;
begin
  vPIDPai := RetornaPID('explorer.exe');
  if vPIDPai <> -1 then
  begin
    vListaProcessosFilhos := RetornaListaprocessosFilhos(vPIDPai);
    for vPIDFilho in vListaProcessosFilhos do
    begin
      ShowMessage(format('Id do processo filho: %d', [vPIDFilho]));
    end;
    FreeAndNil(vListaProcessosFilhos);
  end
  else
    ShowMessage('process não encontrado');
end;

Reference of use of Process32...: Delphitricks

  • As soon as I have time I perform some tests with this method and give a feedback

  • This method is the same as the others I’ve tested... He only comes to find the process "javaw.exe" and I want to know if the process "Demander Synchronizer" is running inside this "javaw.exe". You can tell me if using this method I can search for the "javaw.exe" processes and then check which are your subprocesses?

  • @Matheusribeiro, edited reply!

  • These are very legal methods that I was not aware of, but still not served for what I need, I will change my logic and try to use Createprocess to open the third party program and save its ID for future checks.

0

Whoa, that’s all right?

I was having the same problem. I solved using an excellent blog from an Embarcadero MVP that has helped me a lot in other opportunities. In this blog, he posts an example where you can get the property "Commandline", that brings the subprocesses that are running through the "javaw.exe". That way, I can find what I want in the return text using, for example, a Pos to determine if the name of the process I want is running.

For example, I have two Java programs installed and running on my PC. If I want a call "Myapp", I do the code posted by the blog with small adaptations to search the "Myapp" in sequence. Follows the code:

const
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;// classe Winapi.ActiveX
  iValue        : LongWord;
  vConteudo     : string;
begin
      vConteudo := '';
      FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); // para usar o "CreateOleObject" precisa da classe System.Win.ComObj
      FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
      FWbemObjectSet:= FWMIService.ExecQuery(Format('SELECT Name, CommandLine FROM Win32_Process Where Name="%s"',['javaw.exe']),'WQL',wbemFlagForwardOnly);
      oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
      while oEnum.Next(1, FWbemObject, iValue) = 0 do
      begin // função pega em https://theroadtodelphi.com/2011/11/06/wmi-tasks-using-delphi-%E2%80%93-processes/
        vConteudo := vConteudo + Format('Name         %s',[String(FWbemObject.Name)]);
        vConteudo := vConteudo + Format('Command Line %s',[String(FWbemObject.CommandLine)]);
        FWbemObject:=Unassigned;
      end;

      if Pos('MyApp',vConteudo) > 0 then
        ShowMessage('achou')
      else
        ShowMessage('não achou');

Note that, among the processes being searched for in Win32_process, I seek as name the 'javaw.exe' (indicating that the Java VM is running). Then, after bringing the result, I search inside the variable I loaded with all the content (called "vConteudo") if what you want is there.

At least for me, it has worked perfectly. I have run on Windows 10 (64 and 32 bits) and Windows 7 (32 bits). But I believe it should work on other Windows too - remembering that it only works on Windows, no Linux, for example.

I hope I’ve been clear in my explanation.

Credits for the author, Rodrigo Ruz, at: https://theroadtodelphi.com/2011/11/06/wmi-tasks-using-delphi-%E2%80%93-processes/

PS: utilizo Rad Studio 10 Seattle

  • Thank you! Actually I ended up creating my own project in Delphi and integrating it to my main project, so no longer depending on the third party application. As soon as I have time I’ll take a closer look at your answer.

Browser other questions tagged

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