HOWTO: Get the Filename Given a Window Handle

Last reviewed: June 27, 1997
Article ID: Q119163
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with: - Microsoft Windows NT versions 3.1, 3.5

SUMMARY

To find the filename of the program that created a given window under Windows, you would use GetWindowLong(hWnd, GWL_HINSTANCE) to find the module handle and then GetModuleFileName() to find the filename. This method cannot be used under Windows NT because instance handles are not global, but are unique to the address space in which the application is running.

If the application that created the window is a Windows-based application, the name returned is "ntvdm". To get the actual filename, you need to spawn a Win16 application that will call GetModuleFileName() and pass the filename back to your application using some form of interprocess communication (IPC).

MORE INFORMATION

To find the filename of an application once you have its window handle, first use GetWindowThreadProcessId() to find the process ID (PID) of the process that created the window. Using the PID, query the registry for the performance data associated with the process. To do this, you have to enumerate all processes in the system, comparing each PID to the PID of the process that you are looking for, until the data for that process is found. (This data includes the name of the process.)

The following sample code demonstrates how to find the filename of the Program Manager, PROGMAN.EXE, after obtaining its window handle:

Sample Code

   #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;

      // Get window handle of Program Manager's main window.

      hWnd = FindWindow( "Progman", NULL );

      // Get PID of Program Manager.

      GetWindowThreadProcessId( hWnd, &dwActiveProcessId );

      // Display name of Program Manager's executable file.

      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;

      // Get the index for the PROCESS object.
      GetIndex( "Process", szIndex );

      // Get memory for PPERF_DATA_BLOCK.
      pdb = (PPERF_DATA_BLOCK) HeapAlloc( GetProcessHeap(),
                                          HEAP_ZERO_MEMORY,
                                          dwBytes);

      // Get performance data.
      while( RegQueryValueEx(HKEY_PERFORMANCE_DATA, (LPTSTR)szIndex, NULL,
                             NULL, (LPBYTE)pdb, &dwBytes) ==
   ERROR_MORE_DATA )
      {
         // Increase memory.
         dwBytes += 1000;

         // Allocated memory is too small; reallocate new memory.
         pdb = (PPERF_DATA_BLOCK) HeapReAlloc( GetProcessHeap(),
                                               HEAP_ZERO_MEMORY,
                                               (LPVOID)pdb,
                                               dwBytes);
      }

      // Get PERF_OBJECT_TYPE.
      pot = (PPERF_OBJECT_TYPE)((PBYTE)pdb + pdb->HeaderLength);

      // Get the first counter definition.
      pcd = (PPERF_COUNTER_DEFINITION)((PBYTE)pot + pot->HeaderLength);

      // Get index value for 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));
      }

      // Get the first instance of the object.
      pid = (PPERF_INSTANCE_DEFINITION)((PBYTE)pot + pot-
   >DefinitionLength);

      // Get the name of the first process.
      pcb = (PPERF_COUNTER_BLOCK) ((PBYTE)pid + pid->ByteLength );
      CurrentProcessId = *((DWORD *) ((PBYTE)pcb + dwProcessIdOffset));

      // Find the process object for PID passed in, then print its
      // filename.

      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" );

      // Free the allocated memory.
      if( !HeapFree(GetProcessHeap(), 0, (LPVOID)pdb) )
         printf( "HeapFree failed in main.\n" );

      // Close handle to the key.
      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;

      // Open the key.
      RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                    Key,
                    0, KEY_READ,
                    &hKeyIndex );

      // Get the size of the counter.
      RegQueryValueEx( hKeyIndex,
                       "Counter",
                       NULL, NULL, NULL,
                       &dwBytes );

      // Allocate memory for the buffer.
      pszBuffer = (char *) HeapAlloc( GetProcessHeap(),
                                      HEAP_ZERO_MEMORY,
                                      dwBytes );

      // Get the titles and counters.
      RegQueryValueEx( hKeyIndex,
                       "Counter",
                       NULL, NULL,
                       (LPBYTE)pszBuffer,
                       &dwBytes );

      // Find the index value for 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;
      }

      // Deallocate the memory.
      HeapFree( GetProcessHeap(), 0, (LPVOID)pszBuffer );

      // Close the key.
      RegCloseKey( hKeyIndex );
   }

REFERENCES

For more information on working with the performance data, please see one or all of the following references:

  • The "Win32 Programmer's Reference."
  • The "Windows NT Resource Kit," volume 3.
  • The source code for PView that is included in the Win32 SDK.
  • The "Windows/MS-DOS Developer's Journal," April 1994.


Additional query words: file name
Keywords : BseMisc kbprg
Version : 3.1 3.5
Issue type : kbhowto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: June 27, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.