Solved

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

Posted on 2001-08-03
5
1,299 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
  • 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
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…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…

863 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

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now