关于C ++:获取内存地址输出功能

Get memory address output function

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

1
2
3
4
5
6
7
8
9
10
11
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);
        }
    }
}


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

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

1
2
3
4
5
6
7
8
9
10
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:

1
2
3
4
5
6
7
8
9
10
11
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);
}

1
2
3
4
5
6
7
8
9
10
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()
}

1
2
3
4
5
6
7
8
9
10
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);
}

如果需要,可以通过在C ++ 11和更高版本中使用std::unique_ptr来进一步,以确保HANDLE在超出范围时自动关闭。

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

To retrieve the name of the main executable module for a remote process, use the GetProcessImageFileName or QueryFullProcessImageNamefunction. This is more efficient and more reliable than calling the GetModuleFileNameEx function with a NULL module handle.

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