15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Как получить имя файла данного дескриптора окна

Чтобы найти имя файла программы, которая создала данное окно в 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.