Link to home
Start Free TrialLog in
Avatar of Flupmans
Flupmans

asked on

Check that a specific executable runs in Windows

I wrote a Delphi application, says myapp.exe that should preferrably test when starting that there is no other instance running and, if so, halt. In a first stage, I used a counter in the registry that I put on 1 when starting and 0 when terminating and I tested it at startup. But if for some reason the program aborts, it can't be started because the flag is on 1 and I do not want to ask the user something like 'it looks like this is already running, do you want to continue ?'. I prefer to detect the other really running. Is there some API do check this ?
Avatar of Motaz
Motaz

you can use FindWindow API by one of two methods:

1. You didn't know main application form class name such as TfmMain, and you are sure of the main application
caption such as (My Application Caption)

if FindWindow(nil, 'My Application Caption') > 0 then
  ShowMessage('Application is running')
else
  ShowMessage('Application is not running');

2. You know main form's class name:

if FindWindow('TfmMainApp', nil) > 0
  ShowMessage('Application is running')
else
  ShowMessage('Application is not running');

You should do that in an external application, for example a gaurd for your main application
Motaz
Since you could relay on that windows locks the executable for writing as soon as you start it the first time you could simply test that.. I'm not about the best way to do this but this is one way..

function IsOpen(AAppName: String): Boolean;
var
  FApp: TFileStream;
begin
  try
    FApp:= TFileStream.Create(AAppName, fmOpenWrite);
    Result:= False;
    FApp.Free;
  except
    Result:= True;
  end;
end;
ASKER CERTIFIED SOLUTION
Avatar of -Yoshi-
-Yoshi-

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This should work though....


function TForm1.AlreadyOpen: Boolean;
var
  FTmpHandle: HWND;
  FTitle: String;
begin
  // Searching all next windows
  FTmpHandle:= GetNextWindow(Handle, GW_HWNDNEXT);
  while (GetNextWindow(FTmpHandle, GW_HWNDNEXT) <> 0) do
  begin
    FTmpHandle:= GetNextWindow(FTmpHandle, GW_HWNDNEXT);
    SetString(FTitle, PChar(nil), GetWindowTextLength(FTmpHandle));
    GetWindowText(FTmpHandle, PChar(FTitle), MaxInt);
    if (FTitle=Application.Title) then
    begin
      Result:= True;
      Exit;
    end;
  end;

  // Searching all previous windows
  FTmpHandle:= GetNextWindow(Handle, GW_HWNDPREV);
  while (GetNextWindow(FTmpHandle, GW_HWNDPREV) <> 0) do
  begin
    FTmpHandle:= GetNextWindow(FTmpHandle, GW_HWNDPREV);
    SetString(FTitle, PChar(nil), GetWindowTextLength(FTmpHandle));
    GetWindowText(FTmpHandle, PChar(FTitle), MaxInt);
    if (FTitle=Application.Title) then
    begin
      Result:= True;
      Exit;
    end;
  end;

  Result:= False;
end;
Had some fun rewriting the function... Enjoy!

function TForm1.AlreadyOpen: Boolean;
  function GetTitle(AHandle: HWND): String;
  begin
    SetString(Result, PChar(nil), GetWindowTextLength(AHandle));
    GetWindowText(AHandle, PChar(Result), MaxInt);
  end;

  function Search(AHandle: HWND; AFlag: Cardinal): Boolean;
  begin
    AHandle:= GetNextWindow(AHandle, AFlag);
    if (AHandle <> 0) then
      if (GetTitle(AHandle)=Application.Title) then
        Result:= True
      else
        Result:= Search(AHandle, AFlag)    { Recursive call }
    else
      Result:= False;
  end;
begin
  Result:= Search(GetNextWindow(Handle, GW_HWNDNEXT), GW_HWNDNEXT) or
           Search(GetNextWindow(Handle, GW_HWNDPREV), GW_HWNDPREV)
end;
Avatar of Flupmans

ASKER

For me indeed, checking that myapp.exe is locked is enough as I start it from another .exe