![]() |
Languages »
C / C++ Language »
Utilities
Advanced
License: The Code Project Open License (CPOL)
Process viewerBy Nibu babu thomasLists 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. |
C++ (VC8.0), C, Windows (Win2K, WinXP, Win2003, Vista), MFC, STL, GDI, Dev
|
||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Download ProcViewer.zip - 195.9 KB
Download Exe ProcessViewer.zip - 118.1 KB


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.
I used PSAPI functions provided by microsoft to enumerate the modules loaded by a process.
The API's used are
EnumProcesses -- To get all processes running in the system EnumProcessModules -- To get all modules/dlls loaded by a process GetModuleBaseName -- To get the base name of module... for eg: mydll.dll instead of C:\AnyLongPath\mydll.dll. GetModuleFileNameEx -- To get the long path of a module GetModuleInformation -- Retrieves information pertaining to a module GetProcessMemoryInfo -- To get memory details of a process. 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 GetDeviceDriverBaseName -- To get base name of a device driver GetDeviceDriverFileName -- To get full path of a device driver 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. SearchPath -- Searches PATH environment variable. Docs give a detailed description of the searching process that takes place. GetFileVersionInfo -- For extracting version. GetFileVersionInfoSize -- Size of version 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 ClearItemData(); // Clear tree view m_ctvProcess.DeleteAllItems(); // Clear list view m_clvProcessDetails.DeleteAllItems(); #define MAX 10000 DWORD dwSize = 0; DWORD dwProcIdentifiers[MAX] = { 0 }; EnumProcesses( dwProcIdentifiers, sizeof( dwProcIdentifiers ), &dwSize ); if( !dwSize ) { return; } // 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 = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcIdentifiers[dwIndex] ); if( !hProcModule ) { continue; } DWORD dwModuleSize = 0; HMODULE hModules[MAX] = { 0 }; // Get all modules for a process EnumProcessModules( hProcModule, hModules, sizeof( hModules ), &dwModuleSize ); dwModuleSize /= sizeof( HMODULE ); if( !dwModuleSize ) { continue; } // Structure for storing process information PPROC_INFO_t pstProcInfo = new PROC_INFO_t; if( !pstProcInfo ) { return; } // 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, &pmcProcMemCounter, 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 ) { continue; } // Get module related information GetModuleInformation( hProcModule, hModules[dwModIndex], &( *ppModuleInfo )->stmiModInfo, sizeof( MODULEINFO )); // Get full path of module GetModuleFileNameEx( hProcModule, hModules[dwModIndex], szName, MAX_PATH ); ( *ppModuleInfo )->csModuleFullPath = szName; // Get base name of module GetModuleBaseName( hProcModule, hModules[dwModIndex], szName, 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 ); }
EnumProcesses:
// 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 );
EnumProcessModules:
// 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.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
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.
GetModuleBaseName:
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 )
GetModuleFileNameEx:
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,
&pmcProcMemCounter,
sizeof( pmcProcMemCounter ));
These are the API's that I have used. Main code can be found in ProcessViewerDlg.cpp and ProcessViewerDlg.h
EnumDeviceDrivers
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.
GetDeviceDriverBaseName
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 );
GetDeviceDriverFileName
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 );
GetProcessTimes
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,
&ftStartTime,
&ftExitTime,
&ftKernelTime,
&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.
SearchPath
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...
Usage: // For setting priority use VERIFY( SetPriorityClass( hProcess, ABOVE_NORMAL_PRIORITY_CLASS )); // 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.
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.
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.
To switch from vertical view to horizontal view or vice versa press F6 or second button on toolbar.
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.
To save list of modules for a process press Ctrl + A to select all modules and then Ctrl + C. Things to remember...
The same applies to symbol listing.
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.
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 10 Mar 2008 Editor: |
Copyright 2007 by Nibu babu thomas Everything else Copyright © CodeProject, 1999-2010 Web20 | Advertise on the Code Project |