获取内存地址输出功能

时间:2018-11-17 20:34:10

标签: c++ windows visual-studio winapi

我想将所有winapi与Standart C ++一起使用。如何通过地址传递输出?看起来 o_processName GetModuleFileNameExW 函数参数3需要wchar_t类型。我需要将其转换为wstring类型。当我搜索时,可能是将内存地址传递给 GetModuleFileNameExW 而不是类型。

void GetProcessNameById(DWORD i_processId, std::wstring *o_processName)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
    if (hProcess != NULL)
    {
        if (GetModuleFileNameExW(hProcess, NULL, &o_processName, MAX_PATH))
        {
            CloseHandle(hProcess);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您不能将std::wstring(或任何C ++容器)直接 传递给Win32 API函数。 Win32 API是使用C接口编写的,因此它对C ++类型一无所知。因此,调用API时必须使用C语义。

在您的示例中,您可以分配一个C样式WCHAR[]缓冲区以接收文件名,然后将该缓冲区分配给您的std::wstring

void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
    WCHAR szFileName[MAX_PATH];
    DWORD dwLength = 0;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
    if (hProcess != NULL) {
        dwLength = GetModuleFileNameExW(hProcess, NULL, szFileName, MAX_PATH);
        CloseHandle(hProcess);
    }
    o_processName->assign(szFileName, dwLength);
}

或者,如果要使用C ++容器,则必须预先分配它,然后将其内部数据缓冲区传递给API:

void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
    std::wstring wFileName;
    wFileName.resize(MAX_PATH);
    DWORD dwLength = 0;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
    if (hProcess != NULL) {
        dwLength = GetModuleFileNameExW(hProcess, NULL, &wFileName[0], MAX_PATH); // or wFileName.data() in C++17 and later
        CloseHandle(hProcess);
    }
    o_processName->assign(wFileName.c_str(), dwLength);
}

void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
    std::vector<WCHAR> vecFileName(MAX_PATH, 0);
    DWORD dwLength = 0;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
    if (hProcess != NULL) {
        dwLength = GetModuleFileNameExW(hProcess, NULL, &vecFileName[0], MAX_PATH); // or vecFileName.data() in C++11 and later
        CloseHandle(hProcess);
    }
    o_processName->assign(&vecFileName[0], dwLength); // or vecFileName.data()
}

void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
    std::array<WCHAR, MAX_PATH> arrFileName;
    DWORD dwLength = 0;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
    if (hProcess != NULL) {
        dwLength = GetModuleFileNameExW(hProcess, NULL, arrFileName.data(), MAX_PATH);
        CloseHandle(hProcess);
    }
    o_processName->assign(arrFileName.data(), dwLength);
}

如果需要,您可以在using std::unique_ptr in C++11 and later to ensure the HANDLE is closed automatically when it goes out of scope之前更进一步。

最后,您应该使用GetProcessImageFileNameW()而不是GetModuleFileNameExW()

  

要检索用于远程进程的主要可执行模块的名称,请使用GetProcessImageFileNameQueryFullProcessImageName函数。与使用NULL模块句柄调用GetModuleFileNameEx函数相比,这更有效,更可靠。

此外,由于GetProcessImageFileName()仅需要PROCESS_QUERY_LIMITED_INFORMATION个访问权限,因此与PROCESS_QUERY_INFORMATION | PROCESS_VM_READ相比,您更有可能获得访问权限,尤其是对于系统/受限制的进程。