#include <stdio.h>\r
#include <tchar.h>\r
#include <time.h>\r
+#include <tlhelp32.h>\r
#include "Shlwapi.h"\r
\r
#pragma comment(lib, "psapi.lib")\r
#pragma comment(lib, "shlwapi.lib")\r
\r
-bool gSingleProcess = true;\r
int gQueryInterval = 5; // seconds\r
time_t gDuration = 0; // seconds\r
LPTSTR gCommandLine;\r
HRESULT PrintUsage();\r
void UseImage(void (functionForQueryType(HANDLE)));\r
void QueryContinuously(HANDLE hProcess);\r
+int EvalProcesses(HANDLE hProcess);\r
time_t ElapsedTime(time_t startTime);\r
-unsigned int OneQuery(HANDLE hProcess);\r
-unsigned int OneQueryMP(HANDLE hProcess);\r
\r
int __cdecl _tmain (int argc, TCHAR *argv[])\r
{\r
LPTSTR argument;\r
for( int count = 1; count < argc; count++ ) {\r
argument = argv[count] ;\r
- if (wcsstr(argument, _T("-h")) ||\r
- wcsstr(argument, _T("--help")))\r
+ if (wcsstr(argument, _T("-h")) || wcsstr(argument, _T("--help")))\r
return PrintUsage();\r
else if (wcsstr(argument, _T("--exe"))) {\r
gCommandLine = argv[++count];\r
- if (wcsstr(gCommandLine, _T("chrome.exe")))\r
- gSingleProcess = false;\r
- } else if (wcsstr(argument, _T("-i")) ||\r
+ } else if (wcsstr(argument, _T("-i")) || \r
wcsstr(argument, _T("--interval"))) {\r
gQueryInterval = _wtoi(argv[++count]);\r
if (gQueryInterval < 1) {\r
printf("-i [--interval] arg : Print memory usage every arg seconds. Default: 5 seconds\n");\r
printf("-d [--duration] arg : Run for up to arg seconds. Default: no limit\n\n");\r
printf("Examples:\n");\r
- printf(" record-memory-win --exe \"C:\\Program Files\\Safari\\Safari.exe\"\n");\r
- printf(" record-memory-win --exe Safari.exe -i 10 -d 7200\n");\r
+ printf(" record-memory-win --exe \"C:\\Program Files\\Safari\\Safari.exe /newprocess\"\n");\r
+ printf(" record-memory-win --exe \"Safari.exe /newprocess\" -i 10 -d 7200\n");\r
+ printf(" NOTE: Close all other browser intances to ensure launching in a new process\n");\r
+ printf(" Or, pass the /newprocess (or equivalent) argument to the browser\n");\r
return E_FAIL;\r
}\r
\r
+unsigned int getMemoryInfo(DWORD processID)\r
+{\r
+ unsigned int memInfo = 0;\r
+ HANDLE hProcess;\r
+ PROCESS_MEMORY_COUNTERS_EX pmc;\r
+\r
+ hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |\r
+ PROCESS_VM_READ,\r
+ FALSE, processID );\r
+ if (NULL == hProcess)\r
+ return 0;\r
+\r
+ if (GetProcessMemoryInfo( hProcess, (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc))) {\r
+ memInfo = (pmc.PrivateUsage);\r
+ }\r
+\r
+ CloseHandle( hProcess );\r
+ return memInfo;\r
+}\r
+\r
+void printProcessInfo(DWORD processID)\r
+{\r
+ TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");\r
+ \r
+ // Get a handle to the process.\r
+ HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |\r
+ PROCESS_VM_READ,\r
+ FALSE, processID );\r
+\r
+ // Get the process name.\r
+ if (NULL != hProcess) {\r
+ HMODULE hMod; // An array that receives the list of module handles.\r
+ DWORD cbNeeded; //The number of bytes required to store all module handles in the Module array\r
+\r
+ if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {\r
+ GetModuleBaseName(hProcess, hMod, szProcessName, \r
+ sizeof(szProcessName)/sizeof(TCHAR));\r
+ }\r
+ }\r
+\r
+ // Print the process name and identifier of matching strings, ignoring case\r
+ _tprintf(TEXT("%s (PID: %u)\n"), szProcessName, processID);\r
+ \r
+ // Release the handle to the process.\r
+ CloseHandle( hProcess );\r
+}\r
+\r
+int evalProcesses(HANDLE hProcess)\r
+{\r
+ if (NULL == hProcess)\r
+ return 0;\r
+\r
+ unsigned int totalMemUsage = 0;\r
+ DWORD processID = GetProcessId(hProcess);\r
+ \r
+ HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
+\r
+ PROCESSENTRY32 processEntry = { 0 };\r
+ processEntry.dwSize = sizeof(PROCESSENTRY32);\r
+\r
+ // Retrieves information about the first process encountered in a system snapshot\r
+ if(Process32First(hProcessSnapshot, &processEntry)) {\r
+ do {\r
+ // if th32processID = processID, we are the parent process! \r
+ // if th32ParentProcessID = processID, we are a child process!\r
+ if ((processEntry.th32ProcessID == processID) || (processEntry.th32ParentProcessID == processID)) {\r
+ unsigned int procMemUsage = 0;\r
+ // Record parent process memory\r
+ procMemUsage = getMemoryInfo(processEntry.th32ProcessID);\r
+ totalMemUsage += procMemUsage;\r
+ }\r
+ // Retrieves information about the next process recorded in a system snapshot. \r
+ } while(Process32Next(hProcessSnapshot, &processEntry));\r
+ }\r
+\r
+ CloseHandle(hProcessSnapshot);\r
+ return totalMemUsage;\r
+}\r
+\r
+\r
void UseImage(void (functionForQueryType(HANDLE)))\r
{\r
STARTUPINFO si = {0};\r
&pi )) // Pointer to PROCESS_INFORMATION structure\r
printf("CreateProcess failed (%d)\n", GetLastError());\r
else {\r
- printf("Created process\n");\r
+ printf("Created process with id: %d\n", pi.dwProcessId);\r
functionForQueryType(pi.hProcess);\r
// Close process and thread handles. \r
CloseHandle( pi.hProcess );\r
Sleep(2000); // give the process some time to launch\r
bool pastDuration = false;\r
time_t startTime = time(NULL);\r
- unsigned int memUsage = gSingleProcess ? OneQuery(hProcess) : OneQueryMP(hProcess);\r
+ unsigned int memUsage = evalProcesses(hProcess);\r
while(memUsage && !pastDuration) {\r
printf( "%u\n", memUsage );\r
Sleep(gQueryInterval*1000);\r
- memUsage = gSingleProcess ? OneQuery(hProcess) : OneQueryMP(hProcess);\r
+ memUsage = evalProcesses(hProcess);\r
pastDuration = gDuration > 0 ? ElapsedTime(startTime) > gDuration : false;\r
} \r
}\r
time_t currentTime = time(NULL);\r
return currentTime - startTime;\r
}\r
-\r
-// returns Commit Size (Private Bytes) in bytes\r
-unsigned int OneQuery(HANDLE hProcess)\r
-{\r
- PROCESS_MEMORY_COUNTERS_EX pmc;\r
- if (NULL == hProcess)\r
- return 0;\r
- if (GetProcessMemoryInfo(hProcess, (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc)))\r
- return (unsigned)pmc.PrivateUsage;\r
- return 0;\r
-}\r
-\r
-// returns Commit Size (Private Bytes) in bytes for multi-process executables\r
-unsigned int OneQueryMP(HANDLE hProcess)\r
-{\r
- unsigned int memUsage = 0;\r
- TCHAR monitoredProcessName[MAX_PATH];\r
- GetProcessImageFileName(hProcess, monitoredProcessName, sizeof(monitoredProcessName)/sizeof(TCHAR));\r
- LPTSTR shortProcessName = PathFindFileName(monitoredProcessName);\r
- DWORD aProcesses[1024], cbNeeded, cProcesses;\r
- HANDLE hFoundProcess;\r
- if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))\r
- return 0;\r
-\r
- // Calculate how many process identifiers were returned.\r
- cProcesses = cbNeeded / sizeof(DWORD);\r
- // find existing process\r
- for (unsigned int i = 0; i < cProcesses; i++)\r
- if (aProcesses[i] != 0) {\r
- DWORD retVal = 0;\r
- TCHAR foundProcessName[MAX_PATH];\r
-\r
- // Get a handle to the process.\r
- hFoundProcess = OpenProcess(PROCESS_QUERY_INFORMATION |\r
- PROCESS_VM_READ,\r
- FALSE, aProcesses[i]);\r
-\r
- // Get the process name.\r
- if (NULL != hFoundProcess) {\r
- HMODULE hMod;\r
- DWORD cbNeeded;\r
-\r
- if (EnumProcessModules(hFoundProcess, &hMod, sizeof(hMod), &cbNeeded)) {\r
- GetModuleBaseName(hFoundProcess, hMod, foundProcessName, sizeof(foundProcessName)/sizeof(TCHAR));\r
- if (wcsstr(foundProcessName, shortProcessName))\r
- memUsage += OneQuery(hFoundProcess);\r
- }\r
- }\r
- CloseHandle(hFoundProcess);\r
- }\r
- return memUsage;\r
-}\r