Click here to Skip to main content
15,881,760 members
Articles / Desktop Programming / MFC

Process viewer

Rate me:
Please Sign up or sign in to vote.
4.94/5 (104 votes)
9 Mar 2008CPOL9 min read 454.9K   22K   294   133
Lists out the details of running processes in a system, loaded drivers, loaded dlls, version of each dll and process, process times, command line, owner, priority, GDI resource usage, privileges, loaded symbols, window heirarchy, autostart app finding and more.

Download - 195.9 KB
Download Exe - 118.1 KB

Screenshot - ProcessViewer.jpg

Options Dialog

Screenshot - Options.jpg

Privilege Manager Dialog



A utility application that lists out all the processes that are running in a system along with dll's loaded by them and also displays path of dll's loaded, their load addresses, dll base, image size and per process information.

Features of this tool

  1. Display's all loaded dll's of a process
    • Symbols in each dll, you click on any of them
      • Index
      • Name
      • Address
      • Size
    • Version of each dll
    • Description of dll
    • Company name
    • View each dll with dependency walker if dependency viewing is enabled
    • Full module path, i.e. from where is it loaded?
    • Load address
    • Entry point
    • Image size
    • Load order
  2. Display's all drivers loaded in the system if you click on main kernel process
  3. Process id's
  4. Process owner
  5. Process command line
  6. Process auto startup information
  7. Type of application, i.e. whether application is a console, windows or ms-dos app.
  8. Process priority
  9. GUI resource usage statistics ( Will be expanded in future version )
  10. Size of each process
  11. Symbols in each process
  12. Window details if any
    • Displays windows in it's proper hierarchy i.e. all child windows of a parent window come under it's node.
    • Text or caption
    • HWND
    • Window proc
    • Icon if any
    • Cursor
    • Class of window, i.e Toolbarwindow32 for a toolbar.
    • Thread that owns the window
    • State of window, i.e Maximized, minimized, restored, or invisible
    • Bounds of window
    • ID of window
    • Parent window HWND
    • Class style of window
    • Window styles
    • All child windows for a window displayed hierarchically
  13. Process times
    • Creation time
    • Exit time, i.e. kill a process and then you this time get's updated
    • Kernel mode time, how much of kernel time is used
    • User mode time
  14. File times
    • Creation time
    • Last accessed on
    • Last written on
  15. IO Counters
    • Input and output counter values
  16. Memory details, page fault count etc
  17. Version of process, you get some information also as a tooltip
  18. Privileges of a process along with a privilege manager
  19. Sorting of view
  20. Switching of layout
  21. Kill a process and kill all instances of a process
  22. Search for a process or for a dll/driver loaded
  23. Options dialog for switching off unwanted details
  24. You have an about box. ;)
  25. And an exit button too. ;))

Using the code

I used PSAPI functions provided by microsoft to enumerate the modules loaded by a process.

The API's used are

  1. EnumProcesses -- To get all processes running in the system
  2. EnumProcessModules -- To get all modules/dlls loaded by a process
  3. GetModuleBaseName -- To get the base name of module... for eg: mydll.dll instead of C:\AnyLongPath\mydll.dll.
  4. GetModuleFileNameEx -- To get the long path of a module
  5. GetModuleInformation -- Retrieves information pertaining to a module
  6. GetProcessMemoryInfo -- To get memory details of a process.
  7. EnumDeviceDrivers -- Process with id 4(System) is the process which loads up the drivers, so we use this function to enumerate through these device drivers
  8. GetDeviceDriverBaseName -- To get base name of a device driver
  9. GetDeviceDriverFileName -- To get full path of a device driver
  10. GetProcessTimes -- To get the amount of time each process has taken, when did it start, how much kernel mode, and user mode time has it taken.
  11. SearchPath -- Searches PATH environment variable. Docs give a detailed description of the searching process that takes place.
  12. GetFileVersionInfo -- For extracting version.
  13. GetFileVersionInfoSize -- Size of version
  14. VerQueryValue -- Query for version components. There is a class called FileVersionInfo written for this purpose. Lookup that class for more information on these version functions and how to use them.

This is the main function...

void GetProcessDetails()
   // Clear previous associated item data if any 

   // Clear tree view 

   // Clear list view 

   #define MAX 10000
   DWORD dwSize = 0;
   DWORD dwProcIdentifiers[MAX] = { 0 };
   EnumProcesses( dwProcIdentifiers, sizeof( dwProcIdentifiers ), &dwSize );
   if( !dwSize )
   // Process count 

   dwSize /= sizeof( DWORD ); 
   HTREEITEM hItemRoot = m_ctvProcess.InsertItem( _T( "Process list" ), 60, 60 );
   TCHAR szName[MAX_PATH] = { 0 };
   for( DWORD dwIndex = 0; dwIndex < dwSize; ++ dwIndex )
       HANDLE hProcModule = 
                        dwProcIdentifiers[dwIndex] );
       if( !hProcModule )

       DWORD dwModuleSize = 0;
       HMODULE hModules[MAX] = { 0 };

       // Get all modules for a process 

       EnumProcessModules( hProcModule, 
                           sizeof( hModules ), 
                           &dwModuleSize );
       dwModuleSize /= sizeof( HMODULE );
       if( !dwModuleSize )

       // Structure for storing process information 

       PPROC_INFO_t pstProcInfo = new PROC_INFO_t;
       if( !pstProcInfo )
       // Fill out process information 

       pstProcInfo->dwProcId = dwProcIdentifiers[dwIndex];
       GetModuleFileNameEx( hProcModule, hModules[0], szName, MAX_PATH ); 
       pstProcInfo->csFullPath = szName;
       GetModuleBaseName( hProcModule, hModules[0], szName, MAX_PATH );
       pstProcInfo->csBaseName = szName;

       // Get full path display status, if checked then we will display full path 

       const BOOL bFullPathChecked = 
       m_ToolBar.GetToolBarCtrl().IsButtonChecked( ID_OPTIONS_SHOWPATH ); 

       CString csProc;
       csProc.Format( _T( "%s, PID: %lu" ), 
              SCAST( LPCTSTR , 
               ( bFullPathChecked ? 
                 pstProcInfo->csFullPath : pstProcInfo->csBaseName )), 
              dwProcIdentifiers[dwIndex] );

       HTREEITEM hItem = m_ctvProcess.InsertItem( csProc, 20, 20, hItemRoot );
       m_ctvProcess.SetItemData( hItem, RCAST( DWORD, pstProcInfo ));

       // Process details 

       PROCESS_MEMORY_COUNTERS& pmcProcMemCounter = pstProcInfo->stpmcMemCounters;
       GetProcessMemoryInfo( hProcModule, 
                 sizeof( pmcProcMemCounter ));

       // Insert process memory related values 

       HTREEITEM hPInfoItem = m_ctvProcess.InsertItem( _T( "Details" ), 
                               7, 7, hItem );
       CString csTempStr;
       const int nIconIndex = 63;

       // Page fault count 

       csTempStr.Format( _T( "Page fault count: %lu" ), 
             pmcProcMemCounter.PageFaultCount );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );

       // Page file usage 

       csTempStr.Format( _T( "Page file usage: %.02lf KB" ), 
             pmcProcMemCounter.PagefileUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );
       // Peak page file usage 

       csTempStr.Format( _T( "Peak page file usage: %.02lf KB" ), 
             pmcProcMemCounter.PeakPagefileUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );

       // Peak working set size 

       csTempStr.Format( _T( "Peak working set size: %.02lf KB" ), 
             pmcProcMemCounter.PeakWorkingSetSize/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );

       // Quota non pages pool usage 

       csTempStr.Format( _T( "Quota non paged pool size: %.02lf KB" ), 
             pmcProcMemCounter.QuotaNonPagedPoolUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );

       // Quota pages pool usage 

       csTempStr.Format( _T( "Quota paged pool size: %.02lf KB" ), 
             pmcProcMemCounter.QuotaPagedPoolUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );
       // Quota peak non pages pool usage 

       csTempStr.Format( _T( "Quota peak non paged pool size: %.02lf KB" ), 
             pmcProcMemCounter.QuotaPeakNonPagedPoolUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );
       // Quota peak pages pool usage 

       csTempStr.Format( _T( "Quota peak paged pool size: %.02lf KB" ), 
             pmcProcMemCounter.QuotaPeakPagedPoolUsage/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );
       // Working set size 

       csTempStr.Format( _T( "Working set size: %.02lf KB" ), 
             pmcProcMemCounter.WorkingSetSize/1024.0f );
       m_ctvProcess.InsertItem( csTempStr, nIconIndex, nIconIndex, hPInfoItem );
       // Prepare module list 

       PMODULEINFO_LIST_t* ppModuleInfo = &pstProcInfo->pstModuleInfoList;
       for( DWORD dwModIndex = 1; dwModIndex < dwModuleSize; ++ dwModIndex )
            // Allocate new module 

            *ppModuleInfo = new MODULEINFO_LIST_t;;
            if( !*ppModuleInfo )

            // Get module related information 

            GetModuleInformation( hProcModule, 
                  &( *ppModuleInfo )->stmiModInfo, 
                  sizeof( MODULEINFO ));
            // Get full path of module 

            GetModuleFileNameEx( hProcModule, 
                 MAX_PATH );

            ( *ppModuleInfo )->csModuleFullPath = szName;

            // Get base name of module 

            GetModuleBaseName( hProcModule, 
                               MAX_PATH );
        ( *ppModuleInfo )->csModuleBaseName = szName;
            // Move forward 

            ppModuleInfo = &( *ppModuleInfo )->pstNextModuleInfo;

       }// End for 

       // Close process handle 

       CloseHandle( hProcModule );
    }// End for 

    // Expand root node

    m_ctvProcess.Expand( hItemRoot, TVE_EXPAND );

PSAPI Function usage


// A large array of DWORDs for storing process ids of processes

DWORD dwProcIds[2048];
DWORD dwProcRunning = 0;
// Get all running processes

EnumProcesses( dwProcIds, sizeof( dwProcIds ) /sizeof( dwProcIds[0] ), 
               &dwNeeded );

// To get the count of processes running use

dwProcRunning /= sizeof( DWORD );


// Pass in a large array of modules just to be safe

HMODULE hModuleArray[2048];
DWORD dwModuleCount = 0;
// Open process to get it's handle, for some processes 

// we may be denied access.

                               dwAnyProcessId );
// Get processes 

EnumProcessModules( hProcess, hModuleArray, 
                    sizeof( hModuleArray )/ sizeof( hModuleArray[0] ), 
                    &dwModuleCount );
// Now get actual count of modules loaded

dwModuleCount /= sizeof( HMODULE );

On return the first module in the array is the executable of the process. Rest of the modules will be actual modules loaded.


Returns the base name of a module for eg: if module path is C:\MyPath\Averylongpath\Basename.dll, then this API will return Basename.dll

TCHAR szName[MAX_PATH] = { 0 }
GetModuleBaseName( hProcess, hModule, szName, MAX_PATH )


Very similar to the above function except that it returns full path of the requested module.

GetModuleInformation and GetProcessMemoryInfo:

These two API's are simple to use. Just takes a structure and returns information in them.

// Get module related information

MODULEINFO miModInfo = { 0 };
GetModuleInformation( hProcModule, hModule, &miModInfo, sizeof( MODULEINFO ));

// Get process related information

PROCESS_MEMORY_COUNTERS pmcProcMemCounter = { 0 };
GetProcessMemoryInfo( hProcModule, 
                      sizeof( pmcProcMemCounter ));

These are the API's that I have used. Main code can be found in ProcessViewerDlg.cpp and ProcessViewerDlg.h


Enumerates device drivers loaded by System process. Even though name of the process is shown as System, it's real name is %systemroot%\System32\ntoskrnl.exe.

const int nSize = 2048;
DWORD dwCount = 0;
LPVOID lpvImageBases[nSize] = { 0 };
// Get drivers

EnumDeviceDrivers( lpvImageBases, nSize, &dwCount );

// Get count of drivers loaded

dwCount /= sizeof( LPVOID );

Note that first item in the array is name of the process, rest will be drivers.


Extracts base name of a device driver.

TCHAR szName[MAX_PATH] = { 0 };
// Returns main process name, since we are accessing the first element of the 

// array

GetDeviceDriverBaseName( lpvImageBases[0], szName, MAX_PATH );


Extracts full path of device driver. This didn't work well for me though. Most of the path returned was of the form \Windows\System32\Some.sys etc or \??\C:\..\Some.sys. So I had to use SearchPath API for finding out where exactly these device drivers are located, of course I modified the PATH variable to force this API to look into Drivers folder too.

TCHAR szName[MAX_PATH] = { 0 };
// Returns full path of device driver loader process, since we are accessing 

// first element of the array.

GetDeviceDriverFileName( lpvImageBases[0], szName, MAX_PATH );


Returns timing information for a specified process.

HANDLE hProcess; // Handle returned by OpenProcess

// Prepare filetime structures

FILETIME ftStartTime = { 0 }, 
         ftExitTime = { 0 }, 
         ftKernelTime = { 0 }, 
         ftUserTime = { 0 }
// Get time

GetProcessTimes( hProcess, 
                 &ftUserTime );

You can directly use FILETIME, but should be careful, except for start time and exit time, others won't work as expected (read the docs). You need to do some addtional work on Kernel time and user time.

Best way is to either call FileTimeToSystemTime or put it into a COleDateTime. DavidCrow has written a nice article on this topic. I recommend you read it.


Read the docs carefully for this function. It's a waste of time to describe the working of this API here, since it's well documented.

const int nAllocLength = MAX_PATH * 2;
TCHAR szPathBuffer[ nAllocLength ];

// Search for file 

if( SearchPath( 0, _T( "Anyfile.anytype" ), 0<;/span>, nAllocLength, szPathBuffer, 0 ))
     csFilePath_o = szPathBuffer;
     return true;
}// End if


To change priority of a process call SetPriorityClass, to retrieve priority of a process call GetPriorityClass.

The six classes of priority are as follows...


// For setting priority use


// For retrieving priority use

VERIFY( GetPriorityClass( hProcess ) != 0 );


Process viewer supports searching of loaded modules. You can search for a particular process or a dll. Search does not support wildcard searching, just does an "StrStrI" search. So if you search for "shell", hits will be "shell32.dll" "someshell.dll" "myShelldll.dll etc.

Press Ctrl + F to search.

Dependency viewing

Double click on any module or process to view it's dependency. You should have dependency walker installed on your system. This will happen only if dependency viewing is enabled. One of the toolbar buttons(fourth one) is for this purpose.

You can download dependency walker from here.

Full path

To view full path of a loaded process just enable full path by clicking on green tick button(third one) on toolbar.


To refresh either click first button on toolbar or press F5.

Swap view

To switch from vertical view to horizontal view or vice versa press F6 or second button on toolbar.

Kill Process

Select a particular process to kill. Press F8 or click on the kill button. When a process is killed it's not removed from the process listing instead the process name is set to bold. Press F5/Refresh for removing killed process from tree. Mainly done for retaining snapshot for that process. Helps if there is some trojan running and you want to see a detailed information for that trojan without having the trojan running.

NOTE: Do not kill the kernel process, I tried and the whole system came down. :)


Press F7 for displaying options dialog. You can set various options for process viewing. Options will include much more.

CSV Module listing and symbol listing

To save list of modules for a process press Ctrl + A to select all modules and then Ctrl + C. Things to remember...

  1. If cursor is on an item then that subitem(s) will be copied to clipboard. So to copy more than one sub item, first select required sub items then put your cursor on that sub item column to copy to clipboard.
  2. To copy entire contents take cursor out of list view.
  3. Open notepad and paste.
  4. Save as anyfilename.csv.
  5. Open with a CSV viewer like Excel.

The same applies to symbol listing.

View aspect saving

Saves your settings to an ini file. For eg: column order, divider pane size, main window size. This enables you to change order of list view to your liking. Even sizes of columns are saved.


There is a FileVersionInfo class and DividerWnd class which can reused. A WindowCollection class for enumerating all open windows.

FileVersionInfo extracts version information from a module. DividerWnd is a simple lightweight splitter.


  1. The bitmap that you see in this application's treeview and listview, has been taken from Dominik's Keepass app.
  2. Hey Ralph thanks for those comments. I have implemented most of them, but a rewrite is pending (Reusability). Thanks once again.
  3. Thanks to DavidCrow for his article on Process times.
  4. Thanks to Todd C Wilson for his article on Aggressive optimizations and I am using his header file(I've commented out linker commands that merge sections).
  5. Thanks to CodeProject. Thanks to all those developers who helped me by posting those wonderful articles. If it was not for them then this wouldn't have happened. :)


  1. Created on 05/08/2007.
  2. Added "Search" on 05/14/2007.
  3. Added description of application on 05/16/2007.
  4. Updated application to show loaded device drivers, version information, size, GUI change.
  5. Added progress bar, display of icons related to a process, type of process(Console, Windows, MS-DOS) on 05/28/07.
  6. Added support for sorting, column re-ordering and saving this order on 05/31/2007.
  7. Added extraction of HWND's from running processes. Changed toolbar format. On 06/02/2007.
  8. Added HWND style listing, parent listing. On 06/05/2007.
  9. Made toolbar transparent, enabled window style, id viewing. On 06/07/2007.
  10. Disabled window style viewing due to some issues, fixing going on. On 06/08/2007.
  11. Added options dialog and various different tweaks. On 06/09/2007.
  12. Added kill process option, fixed some issues for saving settings. On 06/10/2007.
  13. Added process priority, and IO counters. On 06/13/2007.
  14. Now correctly displays kids of windows. On 06/18/2007.
  15. Added symbol listing for each loaded module of a process. On 06/25/2007.
  16. Added process privilege display. On 06/26/2007.
  17. Added process owner, process command line, and total window count display. On 10/14/2007.
  18. Added dynamic process priority updation support. On 10/24/07
  19. Added window icon, charset, enabled/disabled status to window details and added support for process priority boost. On 10/26/07
  20. Changed root node text to machine name and user name ;). On 11/2/2007
  21. Finds out whether a process is registered for auto startup. On 11/12/2007
  22. Re-Enabled window style viewing after some bug fixes. On 11/27/2007
  23. Fixed compilation errors in VS2005 (Note: You will get a manifest error in VS2005, so as a fix delete the manifest resource in the resource editor).
  24. Kill all instances of an application support added. Also added "Open parent folder", "Properties" support for processes.
  25. Added privilege manager which helps in dynamically enabling/disabling/removing privileges(Fine tuning needed though). On 1/Jan/2008(Happy new year!)
  26. Optimized a bit for speed!


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Software Developer Microsoft
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

GeneralRe: Doesn't run on W2K Pin
Nibu babu thomas26-Nov-07 17:22
Nibu babu thomas26-Nov-07 17:22 
GeneralRe: Doesn't run on W2K Pin
jos-man17-Dec-07 14:32
jos-man17-Dec-07 14:32 
GeneralRe: Doesn't run on W2K Pin
Nibu babu thomas17-Dec-07 16:17
Nibu babu thomas17-Dec-07 16:17 
GeneralNeed to check if a process is running on local or remote PC using microsoft VC++ 2005 Pin
Developer C++19-Nov-07 21:09
Developer C++19-Nov-07 21:09 
GeneralRe: Need to check if a process is running on local or remote PC using microsoft VC++ 2005 Pin
Nibu babu thomas26-Nov-07 17:38
Nibu babu thomas26-Nov-07 17:38 
QuestionHow to get files opened by process. Pin
champ2319-Nov-07 19:16
champ2319-Nov-07 19:16 
AnswerRe: How to get files opened by process. Pin
Nibu babu thomas19-Nov-07 19:26
Nibu babu thomas19-Nov-07 19:26 
GeneralRe: How to get files opened by process. Pin
champ2319-Nov-07 20:09
champ2319-Nov-07 20:09 
thanks for reply.
I am doing application for Windows mobile.
On that I wanted know which process has opened which file.

GeneralRe: How to get files opened by process. Pin
Nibu babu thomas27-Nov-07 1:14
Nibu babu thomas27-Nov-07 1:14 
GeneralCannot be compiled with VS 2005 Pin
dtr111-Nov-07 4:14
dtr111-Nov-07 4:14 
QuestionRe: Cannot be compiled with VS 2005 Pin
lgzhang22-Nov-07 19:48
lgzhang22-Nov-07 19:48 
AnswerRe: Cannot be compiled with VS 2005 [modified] Pin
Nibu babu thomas29-Nov-07 16:54
Nibu babu thomas29-Nov-07 16:54 
Questionprocess handles? Pin
Huisheng Chen30-Oct-07 3:09
Huisheng Chen30-Oct-07 3:09 
JokeWell done man [modified] Pin
OscarTV21-Aug-07 4:46
OscarTV21-Aug-07 4:46 
GeneralRe: Well done man Pin
Nibu babu thomas21-Aug-07 20:57
Nibu babu thomas21-Aug-07 20:57 
GeneralRe: Well done man Pin
OscarTV21-Aug-07 22:56
OscarTV21-Aug-07 22:56 
GeneralRe: Well done man Pin
srun_jacklee21-Nov-07 19:48
srun_jacklee21-Nov-07 19:48 
GeneralWorking On VISTA Pin
saxena durgesh23-Jul-07 22:33
saxena durgesh23-Jul-07 22:33 
GeneralRe: Working On VISTA [modified] Pin
Nibu babu thomas23-Jul-07 23:36
Nibu babu thomas23-Jul-07 23:36 
GeneralGreat and nice tool, great help Pin
Andi Sielicki19-Jul-07 2:26
Andi Sielicki19-Jul-07 2:26 
GeneralRe: Great and nice tool, great help Pin
Nibu babu thomas19-Jul-07 3:08
Nibu babu thomas19-Jul-07 3:08 
GeneralNice tool Pin
neatapaul18-Jul-07 6:00
neatapaul18-Jul-07 6:00 
GeneralRe: Nice tool Pin
Nibu babu thomas18-Jul-07 20:44
Nibu babu thomas18-Jul-07 20:44 
QuestionWhy some paths abbreviated DOS-Style? Pin
chrislhp6-Jul-07 22:50
chrislhp6-Jul-07 22:50 
AnswerRe: Why some paths abbreviated DOS-Style? Pin
Nibu babu thomas9-Jul-07 22:53
Nibu babu thomas9-Jul-07 22:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.