Solved

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

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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Table Size and Indexes in SQL Server 6 20
Access Search and Edit Form 6 69
Mixed results 10 69
Slow process to read Excel 15 104
This tutorial is about how to put some of your C++ program's functionality into a standard DLL, and how to make working with the EXE and the DLL simple and seamless.   We'll be using Microsoft Visual Studio 2008 and we will cut out the noise; that i…
This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
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…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

743 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

10 Experts available now in Live!

Get 1:1 Help Now