123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include <windows.h>
- #include <assert.h>
- #include <psapi.h>
- #include <stdio.h>
- #include <tchar.h>
- #include <time.h>
- #include <tlhelp32.h>
- #include "Shlwapi.h"
- #pragma comment(lib, "psapi.lib")
- #pragma comment(lib, "shlwapi.lib")
- int gQueryInterval = 5; // seconds
- time_t gDuration = 0; // seconds
- LPTSTR gCommandLine;
- HRESULT ProcessArgs(int argc, TCHAR *argv[]);
- HRESULT PrintUsage();
- void UseImage(void (functionForQueryType(HANDLE)));
- void QueryContinuously(HANDLE hProcess);
- int EvalProcesses(HANDLE hProcess);
- time_t ElapsedTime(time_t startTime);
- int __cdecl _tmain (int argc, TCHAR *argv[])
- {
- HRESULT result = ProcessArgs(argc, argv);
- if (FAILED(result))
- return result;
- UseImage(QueryContinuously);
- return S_OK;
- }
- HRESULT ProcessArgs(int argc, TCHAR *argv[])
- {
- LPTSTR argument;
- for( int count = 1; count < argc; count++ ) {
- argument = argv[count] ;
- if (wcsstr(argument, _T("-h")) || wcsstr(argument, _T("--help")))
- return PrintUsage();
- else if (wcsstr(argument, _T("--exe"))) {
- gCommandLine = argv[++count];
- } else if (wcsstr(argument, _T("-i")) ||
- wcsstr(argument, _T("--interval"))) {
- gQueryInterval = _wtoi(argv[++count]);
- if (gQueryInterval < 1) {
- printf("ERROR: invalid interval\n");
- return E_INVALIDARG;
- }
- } else if (wcsstr(argument, _T("-d")) ||
- wcsstr(argument, _T("--duration"))) {
- gDuration = _wtoi(argv[++count]);
- if (gDuration < 1) {
- printf("ERROR: invalid duration\n");
- return E_INVALIDARG;
- }
- } else {
- _tprintf(_T("ERROR: unrecognized argument \"%s\"\n"), (LPCTSTR)argument);
- return PrintUsage();
- }
- }
- if (argc < 2 || !wcslen(gCommandLine) ) {
- printf("ERROR: executable path is required\n");
- return PrintUsage();
- }
- return S_OK;
- }
- HRESULT PrintUsage()
- {
- printf("record-memory-win --exe EXE_PATH\n");
- printf(" Launch an executable and print the memory usage (in Private Bytes)\n");
- printf(" of the process.\n\n");
- printf("Usage:\n");
- printf("-h [--help] : Print usage\n");
- printf("--exe arg : Launch specified image. Required\n");
- printf("-i [--interval] arg : Print memory usage every arg seconds. Default: 5 seconds\n");
- printf("-d [--duration] arg : Run for up to arg seconds. Default: no limit\n\n");
- printf("Examples:\n");
- printf(" record-memory-win --exe \"C:\\Program Files\\Safari\\Safari.exe /newprocess\"\n");
- printf(" record-memory-win --exe \"Safari.exe /newprocess\" -i 10 -d 7200\n");
- printf(" NOTE: Close all other browser intances to ensure launching in a new process\n");
- printf(" Or, pass the /newprocess (or equivalent) argument to the browser\n");
- return E_FAIL;
- }
- unsigned int getMemoryInfo(DWORD processID)
- {
- unsigned int memInfo = 0;
- HANDLE hProcess;
- PROCESS_MEMORY_COUNTERS_EX pmc;
- hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
- PROCESS_VM_READ,
- FALSE, processID );
- if (NULL == hProcess)
- return 0;
- if (GetProcessMemoryInfo( hProcess, (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc))) {
- memInfo = (pmc.PrivateUsage);
- }
- CloseHandle( hProcess );
- return memInfo;
- }
- void printProcessInfo(DWORD processID)
- {
- TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
-
- // Get a handle to the process.
- HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
- PROCESS_VM_READ,
- FALSE, processID );
- // Get the process name.
- if (NULL != hProcess) {
- HMODULE hMod; // An array that receives the list of module handles.
- DWORD cbNeeded; //The number of bytes required to store all module handles in the Module array
- if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
- GetModuleBaseName(hProcess, hMod, szProcessName,
- sizeof(szProcessName)/sizeof(TCHAR));
- }
- }
- // Print the process name and identifier of matching strings, ignoring case
- _tprintf(TEXT("%s (PID: %u)\n"), szProcessName, processID);
-
- // Release the handle to the process.
- CloseHandle( hProcess );
- }
- int evalProcesses(HANDLE hProcess)
- {
- if (NULL == hProcess)
- return 0;
- unsigned int totalMemUsage = 0;
- DWORD processID = GetProcessId(hProcess);
-
- HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- PROCESSENTRY32 processEntry = { 0 };
- processEntry.dwSize = sizeof(PROCESSENTRY32);
- // Retrieves information about the first process encountered in a system snapshot
- if(Process32First(hProcessSnapshot, &processEntry)) {
- do {
- // if th32processID = processID, we are the parent process!
- // if th32ParentProcessID = processID, we are a child process!
- if ((processEntry.th32ProcessID == processID) || (processEntry.th32ParentProcessID == processID)) {
- unsigned int procMemUsage = 0;
- // Record parent process memory
- procMemUsage = getMemoryInfo(processEntry.th32ProcessID);
- totalMemUsage += procMemUsage;
- }
- // Retrieves information about the next process recorded in a system snapshot.
- } while(Process32Next(hProcessSnapshot, &processEntry));
- }
- CloseHandle(hProcessSnapshot);
- return totalMemUsage;
- }
- void UseImage(void (functionForQueryType(HANDLE)))
- {
- STARTUPINFO si = {0};
- si.cb = sizeof(STARTUPINFO);
- PROCESS_INFORMATION pi = {0};
- // Start the child process.
- if(!CreateProcess( NULL, // No module name (use command line)
- gCommandLine, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- FALSE, // Set handle inheritance to FALSE
- 0, // No creation flags
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &si, // Pointer to STARTUPINFO structure
- &pi )) // Pointer to PROCESS_INFORMATION structure
- printf("CreateProcess failed (%d)\n", GetLastError());
- else {
- printf("Created process with id: %d\n", pi.dwProcessId);
- functionForQueryType(pi.hProcess);
- // Close process and thread handles.
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- }
- }
- void QueryContinuously(HANDLE hProcess)
- {
- Sleep(2000); // give the process some time to launch
- bool pastDuration = false;
- time_t startTime = time(NULL);
- unsigned int memUsage = evalProcesses(hProcess);
- while(memUsage && !pastDuration) {
- printf( "%u\n", memUsage );
- Sleep(gQueryInterval*1000);
- memUsage = evalProcesses(hProcess);
- pastDuration = gDuration > 0 ? ElapsedTime(startTime) > gDuration : false;
- }
- }
- // returns elapsed time in seconds
- time_t ElapsedTime(time_t startTime)
- {
- time_t currentTime = time(NULL);
- return currentTime - startTime;
- }
|