WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Process UDFs

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Get a Processes EXE Name


Question:

I am watching my running processes with a process extender. If there is a new process I want to know where the file of this process is located. Up to this moment I only can get the PID and the name of the process. I think it should be possible to get more information, for Systernals Process explorer can show this info. How to get this info with winbatch ?

Answer:

GetProcessImageFileName API Retrieves the name of the executable file for the specified process.

Note it returns the path in device form, rather than drive letters. For an example, see Memory-Mapped File Information.

A memory-mapped file (or file mapping) is the result of associating a file's contents with a portion of the virtual address space of a process. It can be used to share a file or memory between two or more processes.

The GetMappedFileName function receives a process handle and a pointer to an address as input. If the address is within a memory-mapped file in the virtual address space of the process, the function returns the name of the memory-mapped file. The file names returned by GetMappedFileName use device form, rather than drive letters. For example, the file name c:\winnt\system32\ctype.nls would look like this in device form:

\Device\Harddisk0\Partition1\WINNT\System32\ctype.nls
I put together these UDFs that should help:
#DefineFunction udfGetExePath( prochandle )
   ;Load Dll
   dllname=StrCat(DirWindows(1),"Psapi.dll")

   ;Allocate buffer
   bufsize = 256
   binbuf=BinaryAlloc( bufsize )

   ; Get the Processes filename
   ;DWORD WINAPI GetProcessImageFileName(
   ;  __in   HANDLE hProcess,
   ;  __out  LPTSTR lpImageFileName,
   ;  __in   DWORD nSize
   ;)
   rslt = DllCall( dllname, long:'GetProcessImageFileNameA', long:prochandle,  lpbinary:binbuf, long:256)
   If rslt == 0
      err = DllLastError()
      Message('GetModuleFileNameExA Failed', err )
      Exit
   EndIf

   ; Note DllCalls do not set EOD point in buffer.
   ; EOD Point MUST be set manually with BinaryEODSet
   BinaryEodSet( binbuf, bufsize )  ;
   devicepath = BinaryPeekStr( binbuf, 0, bufsize )

   ;Free buffer
   BinaryFree( binbuf )
   ;Message( 'Window module filename is', filename )
   Return devicepath
#EndFunction


#DefineFunction udfGetDriveLetter(DevicePath)
   ;GetProcessImageFileName, returns  filenames like \Device\HarddiskVolume1\Program Files\Abc.exe
   ;Because these are the real paths as far as the OS is concerned.
   ;You can’t get a DOS drive name directly from this sort of path, instead you’d can use QueryDosDevice
   ;with each drive letter from A to Z and if what it returns matches the path you have, you’ve got your drive letter.
   ;Here’s a little UDF you can use:

   ;Load Dll
   dllname=StrCat(DirWindows(1),"Kernel32.dll")


   ;Loop through the alphabet
   For xx = 1 To 26
         letter = Num2Char(xx+64): ':'

         ;Allocate buffer
         bufsize = 256
         binbuf=BinaryAlloc( bufsize )

         ;DWORD WINAPI QueryDosDevice(
         ;  __in_opt  LPCTSTR lpDeviceName,
         ;  __out     LPTSTR lpTargetPath,
         ;  __in      DWORD ucchMax
         ;);
         rslt = DllCall( dllname, long:'QueryDosDeviceA', lpstr:letter,  lpbinary:binbuf, long:256)
         If rslt == 0
            err = DllLastError()
            ;Message('QueryDosDevice Failed', err )
            Continue
         EndIf
         BinaryEodSet( binbuf, bufsize )  ;
         devicename = BinaryPeekStr( binbuf, 0, bufsize )
         BinaryFree( binbuf )
         ;Compare devive path returned from QueryDosDeviceA to devicepath passed to function
         If StriCmp(devicename, devicepath) == 0
             Return letter
         EndIf
   Next
   Return 0;
#EndFunction


AddExtender("wwprc44I.dll")

;Display a list of processes
proclist=tListProc()
procid = ItemExtract( 2, AskItemlist("All processes",proclist,@TAB,@UNSORTED,@SINGLE) , '|' )

;Get Process Handle
ErrorMode(@OFF)
hProcess=tOpenProc(procid,2)
ErrorMode(@CANCEL)
If hProcess==0
   Message("Unable to open process",tGetLastError())
   Exit
EndIf

;Obtain the device path to the process
devicepath = udfGetExePath( hProcess )

;Parse out device data
devicename = '\' : ItemExtract( 2, devicepath, '\' ) : '\' : ItemExtract( 3, devicepath, '\' )

;Obtain the actual drive letter from the device path
DRIVE = udfGetDriveLetter(devicename)

;Get rest of device path
endpath = ''
cnt = ItemCount( devicepath, '\' )
For index = 4 To cnt
   data = ItemExtract( index, devicepath, '\' )
   endpath = endpath : '\': data
Next

;Append drive letter to path
exepath = DRIVE : endpath
Message( 'Exe Path of Process', exepath )

Exit


Article ID:   W17475
File Created: 2013:04:01:09:22:26
Last Updated: 2013:04:01:09:22:26