2017-01-23 2 views
-1

Я пытаюсь измерить использование памяти процесса (WorkingSetSize) из 64-разрядных приложений из 32-разрядного процесса на C++. Я попытался с помощью Toolhelp:Как измерить использование памяти в 64-битном режиме в 32-разрядной программе?

void GetProcMemoryInfo(const wchar_t * procName) 
{ 
    PROCESSENTRY32 entry; 
    entry.dwSize = sizeof(PROCESSENTRY32); 

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 

    if (Process32First(snapshot, &entry) == TRUE) 
    { 
     while (Process32Next(snapshot, &entry) == TRUE) 
     { 
      if (wcscmp(entry.szExeFile, procName) == 0) 
      { 
       HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); 
       PROCESS_MEMORY_COUNTERS objProcessMemoryInfo; 

       if (GetProcessMemoryInfo(hProcess, &objProcessMemoryInfo, sizeof(objProcessMemoryInfo))) 
       { 
         wchar_t szProcessMemoryInfo[100]; 
         wsprintf(szProcessMemoryInfo, L"Working Set Bytes (MB): %d\n", objProcessMemoryInfo.WorkingSetSize/(1024 * 1024)); 
         OutputDebugString(szProcessMemoryInfo); 
       } 
       CloseHandle(hProcess); 
      } 
     } 
    } 
    CloseHandle(snapshot); 
} 

Это решение отлично работает, но только если это строить, как x64 приложения. В противном случае - получаю максимальное значение 2^32. Я думаю, дело в том, что PROCESS_MEMORY_COUNTERS использует SIZE_T внутренне. Есть ли другой способ измерения использования памяти процесса, нечувствительный к архитектуре, против которой он построен?

+1

Сделайте это из 64-битного процесса, а не изнутри эмулятора –

+0

@DavidHeffernan в нижней строке я должен сделать это из 32-битного процесса. Приложение, которое будет использовать его, будет 32 бит. – pSoLT

+1

Как упоминалось здесь: http://stackoverflow.com/questions/15574638/measuring-process-peak-memory-usage-post-mortem, размер полей в структуре определяется ht-вызовом process'es bitness и переполнение может произойти, если измеренный процесс является x86-64. Поэтому для проведения измерений используйте процесс x86-64. Вы можете написать приложение «прокси», которое будет только измерять память uasage, равную x86-64, а затем передать значение исходному процессу x86 (через удаленный доступ или любой другой IPC). –

ответ

0

Я нашел ответ, и это может быть сделано с использованием Windows Management Instrumentation:

class WMI 
{ 
public: 
    WMI(); 
    ~WMI(); 
    HRESULT Open(LPCTSTR machine=NULL, LPCTSTR user=NULL, LPCTSTR pass=NULL); 
    void Close(); 
    HRESULT GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len); 
    int GetLastError(); 

private: 
    IWbemServices *wbem; 
    HRESULT result; 
    BSTR GetProcQuery(DWORD pid); 
}; 

Для значения свойства извлекается с помощью следующей функции:

HRESULT WMI::GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len) 
{ 
    IWbemClassObject *obj; 
    VARIANT var; 

    result = wbem->GetObject(GetProcQuery(pid), 0, 0, &obj, 0); 

    if (FAILED(result)) { 
     return result; 
    } 

    result = obj->Get(name, 0, &var, 0, 0); 

    if (SUCCEEDED(result)) { 
     if (var.vt == VT_NULL) { 
      result = E_INVALIDARG; 
     } 
     else { 
      lstrcpyn(value, var.bstrVal, len); 
     } 
     VariantClear(&var); 
    } 

    obj->Release(); 

    return result; 
} 

Значение использования памяти является полученной с использованием следующих функций:

int wmiGetMemProc(uint64_t pid, uint64_t *procmem) 
{ 
    int status; 
    TCHAR buf[MEM_MAX]; 
    WMI *wmi = new WMI(); 

    if (FAILED(wmi->Open())) { 
     return wmi->GetLastError(); 
    } 

    if (FAILED(wmi->GetProcStringProperty(pid, L"WorkingSetSize", buf, MEM_MAX))) { 
     status = wmi->GetLastError(); 
    } 
    else { 
     *procmem = _wcstoui64(buf, NULL, 10); 
    } 

    wmi->Close(); 
    delete wmi; 

    return status; 
} 

Это работает просто отлично.

Смежные вопросы