Link to home
Start Free TrialLog in
Avatar of summerset
summerset

asked on

Find if a program is running by exe name not handle?

Hello,

I have a customer that I made a custom app for. I have a timer on the form that does specific tasks every 1 second. One of the new tasks added is that the customer can set the path to an application that will get launched at a specific time. Since I won't know in advance the title of the application, I will need to find if a path to the exe file has been set, and check if it is running. If it is running do nothing. I would shell execute it otherwise. Because I will not know the handle, I cannot use FindWindow -- I will only have the path set to the executable, and I have noticed that other methods do not work with all 32 bit versions of Windows -- 95 thru 2000.

My question is - how can I (by knowing only the path to the executable of the other program) find out if it is running or not -- in all 32 bit versions of Windows? Does anybody have a sample of how this can be done?

Thank you in advance.

-S
Avatar of Gwena
Gwena

listening :-)
ASKER CERTIFIED SOLUTION
Avatar of Madshi
Madshi

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
Hi,

This code should work for all windows versions.
(if not, let me know)

tas

//**********************************************//


Uses
  Psapi, tlhelp32;

procedure CreateWin9xProcessList(List : TStringList) ;
var
  hSnapShot : THandle;
  ProcInfo : TProcessEntry32;
begin
  if List = nil then Exit ;
  hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnapShot <> THandle(-1)) then
  begin
    ProcInfo.dwSize := sizeof(ProcInfo) ;
    if (Process32First(hSnapshot, ProcInfo)) then
    begin
     List.Add( ProcInfo.szExeFile) ;
     while (Process32Next(hSnapShot, ProcInfo)) do
      List.Add(ProcInfo.szExeFile) ;
    end ;
    CloseHandle(hSnapShot) ;
  end ;
end ;

procedure CreateWinNTProcessList(List : TStringList) ;
var
  PIDArray : array [0..1023] of DWORD ;
  cb : DWORD ;
  I : integer ;
  ProcCount : integer ;
  hMod : HMODULE ;
  hProcess : THandle ;
  ModuleName : array [0..300] of char ;
begin
  if List = nil then Exit ;
  EnumProcesses(@PIDArray, sizeof(PIDArray), cb) ;
  ProcCount := cb div sizeof(DWORD) ;
  for I := 0 to ProcCount-1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or
    PROCESS_VM_READ,
    false,
    PIDArray[I]) ;
    if (hProcess <> 0) then
    begin
      EnumProcessModules(hProcess, @hMod, sizeof(hMod), cb) ;
      GetModuleFilenameEx(hProcess,hMod,ModuleName,sizeof(ModuleName));
      List.Add(ModuleName);
      CloseHandle(hProcess);
    end;
  end;
end;

procedure GetProcessList(Var List : TStringList) ;
var ovi : TOSVersionInfo ;
begin
  if List = nil then Exit ;
  ovi.dwOSVersionInfoSize := sizeof(TOSVersionInfo) ;
  GetVersionEx(ovi) ;
  case ovi.dwPlatformId of
    VER_PLATFORM_WIN32_WINDOWS : CreateWin9xProcessList(List) ;
    VER_PLATFORM_WIN32_NT : CreateWinNTProcessList(List) ;
  end
end;

function EXE_ISRunning(FileName : String; fullpath : boolean) : boolean;
var
  i : integer ;
  MyProcList : TStringList;
begin
 MyProcList := TStringList.Create;
 try
   GetProcessList(MyProcList) ;
   result := false;
   if MyProcList = nil then Exit;
    for i := 0 to MyProcList.Count - 1 do
    begin
      if not fullpath then
      begin
       if CompareText(ExtractFileName(MyProcList.Strings[i]),FileName) = 0 then result := true
      end else
       if CompareText(MyProcList.Strings[i],FileName) = 0 then result := true;
     if result then break;
    end;
  finally
   MyProcList.Free ;
 end;
end;


// Example : Is Notepad.exe running ?

procedure TForm1.Button1Click(Sender: TObject);
begin
 if EXE_ISRunning('c:\Windows\notepad.exe',true) then
    ShowMessage('Notepad is running')
 else
    ShowMessage('Notepad is not running');
end;




Avatar of summerset

ASKER

Thank you!
-S
Thanx for the points. BTW, the code posted by Tasomia should also work fine under all systems, however, it needs Microsoft's dll "PsApi.dll" on NT systems. This is not included in all installations, so you would have to distribute the PsApi.dll with your application, quite ugly. My unit doesn't need PsApi.dll.
Thanks, Madshi!

I wish I had more time to go through the whole thing (very hectic schedule). Your code is excellent. The only thing I would ask or suggest would be to include a quick calling sample for each function -- or atleast the important ones as a time saver.

Again -- thank you so much.

-Summerset