Solved

How do i get the file path of a running process in Windows NT.

Posted on 2001-08-03
5
1,303 Views
Last Modified: 2013-12-03
Hello,

How do i get the file path of a running process in Windows NT.
Following is the code to get names of processes running in NT system, which
i got from MSDN.
Is it possible to get Process file path by modifiying following code ?

-------------------------------------------------------
// #define INITIAL_SIZE        51200
#define EXTEND_SIZE         25600
#define REGKEY_PERF         "software\\microsoft\\windows
nt\\currentversion\\perflib"
#define REGSUBKEY_COUNTERS  "Counters"
#define PROCESS_COUNTER     "process"
#define PROCESSID_COUNTER   "id process"
#define UNKNOWN_TASK        "unknown"

DWORD
GetTaskListNT(
PTASK_LIST pTask,
DWORD dwNumTasks
)

/*++

Routine Description:

Provides an API for getting a list of tasks running at the time of the
API call. This function uses the registry performance data to get the
task list and is therefore straight WIN32 calls that anyone can call.

Arguments:

dwNumTasks - maximum number of tasks that the pTask array can hold

Return Value:

Number of tasks placed into the pTask array.

--*/

{
DWORD rc;
HKEY hKeyNames;
DWORD dwType;
DWORD dwSize;
LPBYTE buf = NULL;
CHAR szSubKey[1024];
LANGID lid;
LPSTR p;
LPSTR p2;
PPERF_DATA_BLOCK pPerf;
PPERF_OBJECT_TYPE pObj;
PPERF_INSTANCE_DEFINITION pInst;
PPERF_COUNTER_BLOCK pCounter;
PPERF_COUNTER_DEFINITION pCounterDef;
DWORD i;
DWORD dwProcessIdTitle;
DWORD dwProcessIdCounter;
CHAR szProcessName[MAX_PATH];
DWORD dwLimit = dwNumTasks - 1;



//
// Look for the list of counters. Always use the neutral
// English version, regardless of the local language. We
// are looking for some particular keys, and we are always
// going to do our looking in English. We are not going
// to show the user the counter names, so there is no need
// to go find the corresponding name in the local language.
//
lid = MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL );
sprintf( szSubKey, "%s\\%03x", REGKEY_PERF, lid );
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szSubKey,
0,
KEY_READ,
&hKeyNames
);
if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// get the buffer size for the counter names
//
rc = RegQueryValueEx( hKeyNames,
REGSUBKEY_COUNTERS,
NULL,
&dwType,
NULL,
&dwSize
);

if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// allocate the counter names buffer
//
buf = (LPBYTE) malloc( dwSize );
if (buf == NULL) {
goto exit;
}
memset( buf, 0, dwSize );

//
// read the counter names from the registry
//
rc = RegQueryValueEx( hKeyNames,
REGSUBKEY_COUNTERS,
NULL,
&dwType,
buf,
&dwSize
);

if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// now loop thru the counter names looking for the following counters:
//
// 1. "Process" process name
// 2. "ID Process" process id
//
// the buffer contains multiple null terminated strings and then
// finally null terminated at the end. the strings are in pairs of
// counter number and counter name.
//

p = buf;
while (*p) {
if (p > buf) {
for( p2=p-2; isdigit(*p2); p2--) ;
}
if (stricmp(p, PROCESS_COUNTER) == 0) {
//
// look backwards for the counter number
//
for( p2=p-2; isdigit(*p2); p2--) ;
strcpy( szSubKey, p2+1 );
}
else
if (stricmp(p, PROCESSID_COUNTER) == 0) {
//
// look backwards for the counter number
//
for( p2=p-2; isdigit(*p2); p2--) ;
dwProcessIdTitle = atol( p2+1 );
}
//
// next string
//
p += (strlen(p) + 1);
}

//
// free the counter names buffer
//
free( buf );


//
// allocate the initial buffer for the performance data
//
dwSize = INITIAL_SIZE;
buf = malloc( dwSize );
if (buf == NULL) {
goto exit;
}
memset( buf, 0, dwSize );


while (TRUE) {

rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
szSubKey,
NULL,
&dwType,
buf,
&dwSize
);

pPerf = (PPERF_DATA_BLOCK) buf;

//
// check for success and valid perf data block signature
//
if ((rc == ERROR_SUCCESS) &&
(dwSize > 0) &&
(pPerf)->Signature[0] == (WCHAR)'P' &&
(pPerf)->Signature[1] == (WCHAR)'E' &&
(pPerf)->Signature[2] == (WCHAR)'R' &&
(pPerf)->Signature[3] == (WCHAR)'F' ) {
break;
}

//
// if buffer is not big enough, reallocate and try again
//
if (rc == ERROR_MORE_DATA) {
dwSize += EXTEND_SIZE;
buf = realloc( buf, dwSize );
memset( buf, 0, dwSize );
}
else {
goto exit;
}
}

//
// set the perf_object_type pointer
//
pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);

//
// loop thru the performance counter definition records looking
// for the process id counter and then save its offset
//
pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
for (i=0; i<(DWORD)pObj->NumCounters; i++) {
if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {
dwProcessIdCounter = pCounterDef->CounterOffset;
break;
}
pCounterDef++;
}

dwNumTasks = min( dwLimit, (DWORD)pObj->NumInstances );

pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);

//
// loop thru the performance instance data extracting each process name
// and process id
//
for (i=0; i<dwNumTasks; i++) {
//
// pointer to the process name
//
p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);

//
// convert it to ascii
//
rc = WideCharToMultiByte( CP_ACP,
0,
(LPCWSTR)p,
-1,
szProcessName,
sizeof(szProcessName),
NULL,
NULL
);

if (!rc) {
//
// if we cant convert the string then use a default value
//
strcpy( pTask->ProcessName, UNKNOWN_TASK );
}

if (strlen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {
strcpy( pTask->ProcessName, szProcessName );
strcat( pTask->ProcessName, ".exe" );
}

//
// get the process id
//
pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
pTask->flags = 0;
pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
if (pTask->dwProcessId == 0) {
pTask->dwProcessId = (DWORD)-2;
}

//
// next process
//
pTask++;
pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter +
pCounter->ByteLength);
}

exit:
if (buf) {
free( buf );
}

RegCloseKey( hKeyNames );
RegCloseKey( HKEY_PERFORMANCE_DATA );

return dwNumTasks;
}
-------------------------------------------------------


Thanx,

Nagaraj





0
Comment
Question by:Nagarajhr
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 15

Expert Comment

by:NickRepin
ID: 6351003
HOWTO: Enumerate Applications in Win32
http://support.microsoft.com/support/kb/articles/Q175/0/30.ASP

<<the PSAPI.DLL also contains a variety of useful functions. .... EnumProcesses(), EnumProcessModules(), GetModuleFileNameEx(), GetModuleBaseName()
EnumProcesses()

......

Now you have an array with each process ID in the system. If your goal is to get the name of the process, then you must first get a handle. To get a handle from a process ID, use OpenProcess().

....

To get the first module of a process call the EnumProcessModules()

....

Remember that a process doesn't really have a name, but that the first module in the process is going to be the executable of the process. Now you can use the hModule with the GetModuleFileNameEx(), GetModuleBaseName() to get the full path name, or the simple module name for the process executable.

....

By repeating this for each process ID returned with the EnumProcesses(),you create a list of processes under Windows NT.

>>
0
 

Author Comment

by:Nagarajhr
ID: 6351138
Thank you Mr. NickRepin,

I will check it in my code and reply in another two days.

But i want to know that is it possible to get process file path ( i.e. complete file path of a process in hard disk as C:\WinNT\...\..EXE ) with the help of Process ID or Process name without using PSAPI functions. Because PSAPI functions requires PSAPI DLL, which is not included  in Windows NT ( ver.4 ) system DLLs.
0
 
LVL 15

Accepted Solution

by:
NickRepin earned 200 total points
ID: 6351149
You can re-distribute PSAPI DLL with your application, in case of NT4 prior to Service Pack XXX (sorry, cannot recall the exact number).
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6354946
Both NT4 and Win2k only give you the executable *names*, not the *paths*, when using the performance counters, or when using the undocumented NtGetSystemInformation, or when using the toolhelp functions (Win2k).
The only way of getting the full paths is to either use PsApi.dll (as Nick already pointed out), or doing exactly what PsApi.dll does internally. You can reverse engineer PsApi.dll, it's no big problem (I've done that already).

Regards, Madshi.
0
 

Author Comment

by:Nagarajhr
ID: 6355050
Thank you for your suggestions.

Nagaraj
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows a few slightly more advanced techniques for Windows 7 gadget programming, including how to save and restore user settings for your gadget and how to populate the "details" panel that is displayed in the Windows 7 gadget gallery.  …
This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Finding and deleting duplicate (picture) files can be a time consuming task. My wife and I, our three kids and their families all share one dilemma: Managing our pictures. Between desktops, laptops, phones, tablets, and cameras; over the last decade…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question