Link to home
Start Free TrialLog in
Avatar of Hypoviax
HypoviaxFlag for Australia

asked on

Processes Filepaths

At the moment i use this code to find the filepaths of processes. It is a toolhelp function:

var
  c : cardinal;
  me : TModuleEntry32;
begin
  c := CreateToolhelp32Snapshot(TH32CS_SnapModule, PROCESSPIDHERE);
  me.dwSize := sizeof(me);
  Module32First(c, me);

  ShowMessage(me.szExePath);
  CloseHandle(c);
end;

I have no problem using this function.

The problem is this:

Certain processes filepaths cannot be extracted using this function even if provided the correct PID (i have no problem finding PIDs or enumerating processes). Such processes are svchost.exe, winlogon.exe etc. I have solved this problem by assuming any of these processes reside within %windir%/System32. This is fine for most microsoft programs as this is the case. However, some Norton programs i cannot extract the filepaths using this function and they do not reside in system32. My question is:

Is there other code (i want code no components) that will solve my stated problem?

Regards,

Hypoviax
Avatar of Mikho
Mikho
Flag of Sweden image

SearchPath could maybe help?

Declaration taken from the Win32 Programmer's reference.

The SearchPath function searches for the specified file.
DWORD SearchPath(
    LPCTSTR lpPath,      // address of search path
    LPCTSTR lpFileName,      // address of filename
    LPCTSTR lpExtension,      // address of extension
    DWORD nBufferLength,      // size, in characters, of buffer
    LPTSTR lpBuffer,      // address of buffer for found filename
    LPTSTR *lpFilePart       // address of pointer to file component
   );      
 

lpPath

Points to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence:

1.      The directory from which the application loaded.
      2.      The current directory.
      3.      Windows 95: The Windows system directory. Use the GetSystemDirectory function to get the path of this directory.

Windows NT: The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is SYSTEM32.

4.      Windows NT: The 16-bit Windows system directory. There is no Win32 function that obtains the path of this directory, but it is searched. The name of this directory is SYSTEM.
      5.      The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
      6.      The directories that are listed in the PATH environment variable.

// end

code example below:

var
   Len     : Integer;
   ShortName,
   TempFilePart : string;
   pDummy: PCHAR;
begin
 Len := SearchPath(NIL,'twain.dll',NIL,0, PChar(TempFilePart),pDummy);
 SetLength(TempFilePart, Len);
 SearchPath(NIL,'twain.dll',NIL, Len, PChar(TempFilePart),pDummy);
 Label9.Caption := 'DLL Version: ' + GetFileVersion(Copy(TempFilePart,1,Length(TempFilePart) -1));
end;

fast and maybe not working out of the box :) but its help on the way
SOLUTION
Avatar of Wim ten Brink
Wim ten Brink
Flag of Netherlands image

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
ASKER CERTIFIED SOLUTION
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
Avatar of Hypoviax

ASKER

Thanks,

Will test each today (operating on a different time zone)

Regards,

Hypoviax
Alex,

I have trouble running your example. The IEnumVariant is an 'undeclared identifier'. Is there some unit i need to add to uses? I already have the compiled WMI unit in my uses list.

Hypoviax
Solved it don't worry, needed ActiveX
Haha, "Access Denied" !

What's this mean ?
Ok, I have tested Eddie's and Alex's code

Both work (both with minor flaws)

Alex, your code for some reason  didn't work on my pc ('Accessed denied') however it worked well on another pc. What is the problem here?

Eddie your code worked well too except some processes the filepath is not returned at all. I am sure i can fix this problem (unless you can ;-) )

Regards,

Hypoviax
I don't know why but some of the processes that are started by the system don't "have" paths.
I would guess that you would have to check the see who the process owner was.
Hypoviax, I'm not completely sure but it could be because the user account you used might not have proper access rights. At least, that's the first thing I always consider. Or maybe WMI isn't properly installed. (It should be part of Internet Explorer 5 and higher.) Or maybe the WMI service isn't running if you're using any NT-based Windows version. (On 98/ME it should just be running anyway.)
WMI does return the paths for the system processes, though. But I was never able to test it on all kinds of systems. Theoretically you could just test WMI by creating a small VBScript application retrieving the data in a similar way, though. Then you know if it's an application error or something else.
It is strange, because i am running WinXp, and am an administrator. The thing is it works on my other XP computer fine. So i think that eliminates the user rights issue. I get the error on the third line:

ObjectSet := Services.ExecQuery( Format( sQuery, [ PID ] ), 'WQL', wbemFlagBidirectional, nil );

Regards,

Hypoviax
SOLUTION
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
I am afraid not :( ,but thanks for the comment.You're into this stuff Madshi, do you have a possible solution?. I will still continue testing to try to get the codes to work because at the moment both Alex's and Eddie's code have minor flaws that mean that i won't be able to extract *every* filepath. There seems to be nothing wrong with Alex's code except that it won't run on my system (works on my other one) and Eddie's works well except certain processes do not return a filepath at all. I may be able to fix these problems so don't think that i have forgotton about this question and not awarded points ;-).

Thanks,

Hypoviax
Avatar of Madshi
Madshi

Here's the list of processes, enumerated on my XP PC by using madKernel, while being logged on as admin user:


Without EnableAllPrivileges:
----------------------------
[System Process]
System
C:\WINDOWS\system32\smss.exe
csrss.exe
C:\WINDOWS\system32\winlogon.exe
C:\WINDOWS\system32\services.exe
C:\WINDOWS\system32\lsass.exe
C:\WINDOWS\system32\Ati2evxx.exe
C:\WINDOWS\system32\svchost.exe
svchost.exe
C:\WINDOWS\System32\svchost.exe
svchost.exe
svchost.exe
C:\WINDOWS\system32\Ati2evxx.exe
C:\WINDOWS\Explorer.EXE
C:\WINDOWS\system32\spoolsv.exe
C:\WINDOWS\system32\CTHELPER.EXE
alg.exe
C:\Programme\Mozilla Firefox\FIREFOX.EXE
C:\Programme\Borland\Delphi 7\Bin\delphi32.exe
C:\Sources\mtsM\Mts.exe


With EnableAllPrivileges:
----------------------------
[System Process]
System
C:\WINDOWS\system32\smss.exe
C:\WINDOWS\system32\csrss.exe
C:\WINDOWS\system32\winlogon.exe
C:\WINDOWS\system32\services.exe
C:\WINDOWS\system32\lsass.exe
C:\WINDOWS\system32\Ati2evxx.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\Ati2evxx.exe
C:\WINDOWS\Explorer.EXE
C:\WINDOWS\system32\spoolsv.exe
C:\WINDOWS\system32\CTHELPER.EXE
C:\WINDOWS\System32\alg.exe
C:\Programme\Mozilla Firefox\FIREFOX.EXE
C:\Programme\Borland\Delphi 7\Bin\delphi32.exe
C:\Sources\mtsM\Mts.exe
Hmmm...that might be the problem with Eddie's code then, let me test...
Yep, that fixed Eddie's problem...

Well Madshi, i think you've fixed the problem enough for me to award points ... :-)

When using Eddie's code I'd suggest to replace WinXPor2Kor2K3 with this:

function WinNtFamily : boolean;
begin
  result := GetVersion and $80000000 = 0;
end;

PsApi works on all NT OSs, and it will probably continue to work in Longhorn (at least I'd be surprised if it stopped to work there). Eddie's code is alright, it just limits itself to the known NT OSs, which I don't think is necessary.

P.S: Instead of:

SetLength(FileName, StrLen(PChar(FileName)));

You can do this:

FileName := pchar(FileName);

The wonders of Delphi string handling!   :-)
For anyone else this is the modified version of Eddie's code so that a PID can be given and the filepath returned. For the csrss smss and winlogon processes /??/ needs to be stripped from the front on the filepath :

function getfilepath(PID:Integer):String;
var
    FileName: String;
    Handle: THandle;
begin
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
                                    False, PID);
              if Handle <> 0 then
              try
                SetLength(FileName, MAX_PATH);
                // Use the psapi function GetModuleFileNameEX to get the full path
                if GetModuleFileNameEx(Handle, 0, PChar(FileName), MAX_PATH) > 0 then
                  SetLength(FileName, StrLen(PChar(FileName)))
                else
                  FileName := '';   //doesn't exist apparently
              finally
                CloseHandle(Handle);
              end;
result:=filename;
end;

And thanks for everyone for their assistence and input, it is greatly appreciated.

Best Regards,

Hypoviax
Ok, was typing before i posted that last comment (didn't refresh), I'll make that change

Regards,

Hypoviax
Still, while psAPI might still be supported by LongHorn, I just wonder why the WMI version failed. It's weird since I would assume that MS would never stop supporting WMI but it might drop psAPI in the future.
I agree, it is very strange. It seems there is nothing actually wrong with it but that in some systems (such as mine) a certain access level is required (despite the fact i have administrator rights). But thanks for your efforts Alex, they are much appreciated and i may end up using your code if i can determine what the problem is and how to overcome it

Regards,

Hypoviax
Alex,
 Some systems may not have the WMI service running. If I'm not mistaken you can turn it off.
Is the service called : WMI Performance Adapter.

If so even when i started it (it was not running) i still recieved the Access Denied message. Perhaps i needed to restart ?

Regards,

Hypoviax
Windows Management Instruction (WMI) service was on and to no effect of the error message