1

Using Delphi (windows app) i want to get list of other applications running currently. Here How to check if a process is running using Delphi? i've found great tutorial about geting filenames/names of running application, however it gives names only process name (for example NOTEPAD.EXE). I've used naturally part with

UpperCase(ExtractFileName(FProcessEntry32.szExeFile))

and

UpperCase(ExtractFilePath(FProcessEntry32.szExeFile))

and just

UpperCase(FProcessEntry32.szExeFile)

but obviously FProcessEntry32.szExeFile does not have a path to file/process

Is there a simply way of getting list with paths? Here's How to get the list of running processes including full file path? solution with JclSysInfo library, but i cant use it in place of work in project.

I looked at what I could in Google and what I found usually concerned just the application that is running or the application that is active, but I can't just find a list of all running applications. Maybe i'm missing something obvious?

I'm not looking for any complex procedures, I'm not much interested in process parrent, or if there is no access to the process path, I don't have it and don't bother.

Any simple hint?

OK, due to helpfull comment from @TLama i've combined topics above to take name and path of process:

function processExists(exeFileName: string): Boolean;
var
  ContinueLoopP, ContinueLoopM: BOOL;
  FSnapshotHandle1, FSnapshotHandle2: THandle;
  FProcessEntry32: TProcessEntry32;
  FMODULEENTRY32: TMODULEENTRY32;
begin
  FSnapshotHandle1 := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  FMODULEENTRY32.dwSize := SizeOf(FMODULEENTRY32);
  ContinueLoopP := Process32First(FSnapshotHandle1, FProcessEntry32);
  ContinueLoopM := Module32First(FSnapshotHandle2, FMODULEENTRY32);
  Result := False;
  while Integer(ContinueLoopP) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
      Result := True;
    ShowMessage(FMODULEENTRY32.szExePath + FProcessEntry32.szExeFile);
    ContinueLoopP := Process32Next(FSnapshotHandle1, FProcessEntry32);
    ContinueLoopM := Module32Next(FSnapshotHandle2, FMODULEENTRY32);
  end;
  CloseHandle(FSnapshotHandle1);
  CloseHandle(FSnapshotHandle2);
end;

But still FProcessEntry32.szExeFile returns empty string. What i'm doing wrong? Thank You in advance.

kwadratens
  • 187
  • 15
  • 8
    Windows help explains how to do that. See [PROCESSENTRY32](https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32); they say for the `szExeFile` member *"To retrieve the full path to the executable file, call the Module32First function and check the szExePath member of the MODULEENTRY32 structure that is returned. However, if the calling process is a 32-bit process, you must call the QueryFullProcessImageName function to retrieve the full path of the executable file for a 64-bit process."*. – TLama Dec 22 '19 at 15:41
  • Thank You. I've edited post with code. I still got empty paths. Any ideas what i'm doing wrong? – kwadratens Dec 23 '19 at 15:37
  • @kwadratens As far as I know you need to run your program with elevated privileges in order to be able to retrieve full path otherwise it is partially blocked by UAC (User Account Control). So try running your program as Administrator and see if you will then get full path information. – SilverWarior Dec 24 '19 at 15:43
  • @SilverWarior - I tried in different ways and running the above code both in administrator and other mode on systems, XP, win8.1 and win10 did not bring me results. – kwadratens Dec 28 '19 at 13:38

1 Answers1

3

I cannot write comment (low score), so I need to write as "answer". Try this code, using FProcessEntry32.th32ProcessID as parameter:

Function QueryFullProcessImageNameW(hProcess:THandle; dwFlags:Cardinal; lpExeName:PWideChar; Var lpdwSize:Cardinal) : Boolean; StdCall; External 'Kernel32.dll' Name 'QueryFullProcessImageNameW';

Function GetFullPath(Pid:Cardinal) : UnicodeString;
         Var   rLength:Cardinal;
               Handle:THandle;
         Begin Result:='';
               Handle:=OpenProcess(PROCESS_QUERY_INFORMATION, False, Pid);
               If Handle = INVALID_HANDLE_VALUE Then Exit;
               rLength:=256; // allocation buffer
               SetLength(Result, rLength+1); // for trailing space
               If Not QueryFullProcessImageNameW(Handle, 0, @Result[1],rLength) Then  Result:='' Else SetLength(Result, rLength);
               End;

This is a simple way I think. If you want to get the loaded DLL's full name, use FMODULEENTRY32.hModule with GetModuleFileNameW function.

M1209
  • 41
  • 3
  • 1
    `QueryFullProcessImageName` is not available on every Windows version. – AmigoJack Dec 25 '19 at 00:01
  • @AmigoJack: You are right, I suspected it not a newly developed app for XP. If running on XP is required, there should be an alternate,separated function for XP, but using this code after XP always works. (And of couse, need to link imported functions dinamically, to avoid ldr exception). – M1209 Dec 27 '19 at 08:41
  • I checked this method and in Win8.1 and Win10 it works (YAY! Thank You), this process could not be started for WinXP. Do you know the equivalent of this procedure for WinXP? – kwadratens Dec 28 '19 at 13:41
  • 1
    For XP, use GetProcessImageFileNameW function instead QueryFullProcessImageNameW. The difference is the returning path, so you need to postprocess it. For details, check Microsoft API documentation here [link](https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getprocessimagefilenamew) – M1209 Dec 30 '19 at 01:22
  • @M1209 Thank You. I've used: > Function GetProcessImageFileNameW (hProcess:THandle; dwFlags:Cardinal; lpExeName:PWideChar; Var lpdwSize:Cardinal) : Boolean; StdCall; External 'Kernel32.dll' Name 'GetProcessImageFileNameW'; but in WinXP SE i got message, that is not found in kernel32.dll Anyway - thank You for full support! – kwadratens Dec 30 '19 at 18:04
  • 1
    It's not in Kernel32 on XP, it's in psapi.dll. Also the rLength can be much more bigger too, not limited to 260 chrs. – M1209 Jan 01 '20 at 05:38