Как получить имя файла данного дескриптора
окна
Чтобы найти имя файла программы, которая
создала данное окно в Windows, необходимо
воспользоваться GetWindowLong(hWnd, GWL_HINSTANCE) для
определения дескриптора модуля, а затем
GetModuleFileName() для нахождения имени файла. Данный
метод не работает в Windows NT так как в ней
дескрипторы экземпляров не авляются глобальными,
а уникальны для адресного пространства в котором
выполняется процесс.
Если приложение, которое создало окно является
Windows приложением, то будет возвращено имя
"ntvdm". Чтобы получить фактическое имя файла,
то необходимо породить приложение Win16, которое
будет вызывать GetModuleFileName() и передавать имя файла
обратно в Вашу программу при помощи какого либо
вида межпроцессовых взаимодействий (IPC).
Как только Вы получите дескриптор окна, то для
определения имени файла приложения сперва
воспользуемся GetWindowThreadProcessId() для нахождения
идентификатора (ID) процесса (PID) который создал
окно. Далее, используя PID, сделаем запрос в реестр,
в ту часть, где находятся данные о
производительности, связанные с процессом. Для
этого нам потребуется перечислить все процессы в
системе, сравнить каждый PID с PID процесса, который
мы ищем, до тех пор, пока данные процесса не будут
найдены. (Эти данные включают и имя процесса.)
Следующий пример демонстрирует, как найти имя
файла Program Manager, PROGMAN.EXE, после получения
дескриптора окна:
Пример кода
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define Key "SOFTWARE\\Microsoft\\Windows
NT\\CurrentVersion\\Perflib\\009"
void GetIndex( char *, char * );
void DisplayFilename( DWORD );
/********************************************************************\
* Function: void main( ) *
* *
* Purpose : Application entry point *
* *
\********************************************************************/
void main( )
{
HWND hWnd;
DWORD dwActiveProcessId;
// Получаем дескриптор основного окна Program Manager.
hWnd = FindWindow( "Progman", NULL );
// Получаем PID Program Manager.
GetWindowThreadProcessId( hWnd, &dwActiveProcessId );
// Отображаем имя исполняемого файла Program Manager.
printf( "Searching for filename of Program Manager...\n" );
DisplayFilename( dwActiveProcessId );
}
/********************************************************************\
* Function: void DisplayFilename( DWORD ) *
* *
* Purpose : Display executable filename of the process whose PID *
* is passed in as a parameter. *
* *
* Comment : The information is retrieved from the performance *
* data in the registry. *
* *
\********************************************************************/
void DisplayFilename( DWORD dwProcessId )
{
DWORD CurrentProcessId;
BOOL bContinue = TRUE;
char szIndex[256] = "";
DWORD dwBytes = 12000;
DWORD dwProcessIdOffset;
int i;
PPERF_DATA_BLOCK pdb;
PPERF_OBJECT_TYPE pot;
PPERF_INSTANCE_DEFINITION pid;
PPERF_COUNTER_BLOCK pcb;
PPERF_COUNTER_DEFINITION pcd;
// Получаем индекс для объекта PROCESS.
GetIndex( "Process", szIndex );
// Выделяем память для PPERF_DATA_BLOCK.
pdb = (PPERF_DATA_BLOCK) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBytes);
// Получаем данные производительности.
while( RegQueryValueEx(HKEY_PERFORMANCE_DATA, (LPTSTR)szIndex, NULL,
NULL, (LPBYTE)pdb, &dwBytes) ==
ERROR_MORE_DATA )
{
// Увеличиваем память.
dwBytes += 1000;
// Распределённая память мала; перераспределяем новую память.
pdb = (PPERF_DATA_BLOCK) HeapReAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
(LPVOID)pdb,
dwBytes);
}
// Получаем PERF_OBJECT_TYPE.
pot = (PPERF_OBJECT_TYPE)((PBYTE)pdb + pdb->HeaderLength);
// Получаем объявление первого счётчика.
pcd = (PPERF_COUNTER_DEFINITION)((PBYTE)pot + pot->HeaderLength);
// Получаем значение индекса для ID_PROCESS.
szIndex[0] = '\0';
GetIndex( "ID Process", szIndex );
for( i=0; i< (int)pot->NumCounter; i++ )
{
if (pcd->CounterNameTitleIndex == (DWORD)atoi(szIndex))
{
dwProcessIdOffset = pcd->CounterOffset;
break;
}
pcd = ((PPERF_COUNTER_DEFINITION)((PBYTE)pcd + pcd->ByteLength));
}
// Получаем первый экземпляр объекта.
pid = (PPERF_INSTANCE_DEFINITION)((PBYTE)pot + pot-
>DefinitionLength);
// Получаем имя первого процесса.
pcb = (PPERF_COUNTER_BLOCK) ((PBYTE)pid + pid->ByteLength );
CurrentProcessId = *((DWORD *) ((PBYTE)pcb + dwProcessIdOffset));
// Находим объект процесса для переданного PID, а затем
// печатаем его имя файла.
for( i = 1; i < pot->NumInstances && bContinue; i++ )
{
if( CurrentProcessId == dwProcessId )
{
printf( "The filename is %ls.exe.\n",
(char *) ((PBYTE)pid + pid->NameOffset) );
bContinue = FALSE;
}
else
{
pid = (PPERF_INSTANCE_DEFINITION) ((PBYTE)pcb + pcb-
>ByteLength);
pcb = (PPERF_COUNTER_BLOCK) ((PBYTE)pid + pid->ByteLength);
CurrentProcessId = *((DWORD *)((PBYTE)pcb +
dwProcessIdOffset));
}
}
if( bContinue == TRUE )
printf( "Not found.\b" );
// Освобождаем распределённую память.
if( !HeapFree(GetProcessHeap(), 0, (LPVOID)pdb) )
printf( "HeapFree failed in main.\n" );
// Закрываем дескриптор ключа.
RegCloseKey( HKEY_PERFORMANCE_DATA );
}
/********************************************************************\
* Function: void GetIndex( char *, char * ) *
* *
* Purpose : Get the index for the given counter *
* *
* Comment : The index is returned in the parameter szIndex *
* *
\********************************************************************/
void GetIndex( char *pszCounter, char *szIndex )
{
char* pszBuffer;
char* pszTemp;
char szObject[256] = "";
DWORD dwBytes;
HANDLE hKeyIndex;
int i = 0;
int j = 0;
// Открываем ключ.
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
Key,
0, KEY_READ,
&hKeyIndex );
// Получаем размер счётчика.
RegQueryValueEx( hKeyIndex,
"Counter",
NULL, NULL, NULL,
&dwBytes );
// Распределяем память для буфера.
pszBuffer = (char *) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBytes );
// Получаем заголовки и счётчики.
RegQueryValueEx( hKeyIndex,
"Counter",
NULL, NULL,
(LPBYTE)pszBuffer,
&dwBytes );
// Находим значение индекса для PROCESS.
pszTemp = pszBuffer;
while( i != (int)dwBytes )
{
while (*(pszTemp+i) != '\0')
{
szIndex[j] = *(pszTemp+i);
i++;
j++;
}
szIndex[j] = '\0';
i++;
j = 0;
while (*(pszTemp+i) != '\0')
{
szObject[j] = *(pszTemp+i);
i++;
j++;
}
szObject[j] = '\0';
i++;
j = 0;
if( *(pszTemp+i) == '\0' )
i++;
if( strcmp(szObject, pszCounter) == 0 )
break;
}
// Освобождаем память.
HeapFree( GetProcessHeap(), 0, (LPVOID)pszBuffer );
// Закрываем ключ.
RegCloseKey( hKeyIndex );
}
ССЫЛКИ
Более подробную информацию о работе с данными
производительности смотрите в следующих раздела:
- "Win32 Programmer's Reference."
- "Windows NT Resource Kit," volume 3.
- Исходный код PView который включён в Win32 SDK.
|