You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ReadProcessMemory读取Wesnoth游戏内存失败问题求助

问题排查与解决方法

1. 先检查所有API调用的返回状态

你的代码没有做任何错误检查,这是核心问题——FindWindow可能没找到窗口、OpenProcess可能权限不足失败,最终导致ReadProcessMemory无法正常工作。先修改代码加上错误判断:

#include <windows.h>
#include <iostream>

int main(int argc, char** argv) {
    HWND wesnoth_window = FindWindowW(nullptr, L"The Battle for Wesnoth - 1.14.9");
    if (!wesnoth_window) {
        std::cout << "找不到游戏窗口,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    DWORD process_id = 0;
    GetWindowThreadProcessId(wesnoth_window, &process_id);
    if (process_id == 0) {
        std::cout << "获取进程ID失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    // 只申请需要的读权限,避免用PROCESS_ALL_ACCESS(权限过高易失败)
    HANDLE wesnoth_process = OpenProcess(PROCESS_VM_READ, FALSE, process_id);
    if (!wesnoth_process) {
        std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    DWORD gold_value = 0;
    SIZE_T bytes_read = 0; // 注意用SIZE_T类型,匹配ReadProcessMemory的参数要求
    BOOL read_ok = ReadProcessMemory(wesnoth_process, (LPCVOID)0x017EED8, &gold_value, sizeof(gold_value), &bytes_read);
    if (!read_ok) {
        std::cout << "读取内存失败,错误码:" << GetLastError() << std::endl;
    } else {
        std::cout << "读取成功:字节数=" << bytes_read << ",金币值=" << gold_value << std::endl;
    }

    CloseHandle(wesnoth_process);
    return 0;
}

2. 排查32位/64位兼容性问题

如果游戏是64位程序,但你的调试程序编译为32位:

  • 32位程序无法正确访问64位进程的地址空间,必须把自己的程序改成64位编译。
  • 地址类型改用uintptr_t或DWORD_PTR,避免32位类型截断64位地址。

3. 确认内存地址是否为固定绝对地址

CheatEngine里显示的0x017EED8大概率不是固定绝对地址,而是游戏主模块(比如wesnoth.exe)的偏移量。每次重启游戏,模块加载基址会变化,导致绝对地址失效。需要先获取模块基址再计算真实地址:

// 获取进程主模块基址的工具函数
uintptr_t GetModuleBaseAddress(DWORD processId, const wchar_t* moduleName) {
    uintptr_t baseAddr = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        MODULEENTRY32W moduleEntry;
        moduleEntry.dwSize = sizeof(MODULEENTRY32W);
        if (Module32FirstW(hSnapshot, &moduleEntry)) {
            do {
                if (_wcsicmp(moduleEntry.szModule, moduleName) == 0) {
                    baseAddr = (uintptr_t)moduleEntry.modBaseAddr;
                    break;
                }
            } while (Module32NextW(hSnapshot, &moduleEntry));
        }
        CloseHandle(hSnapshot);
    }
    return baseAddr;
}

// 在main函数中调用
uintptr_t moduleBase = GetModuleBaseAddress(process_id, L"wesnoth.exe");
if (moduleBase == 0) {
    std::cout << "获取模块基址失败" << std::endl;
    CloseHandle(wesnoth_process);
    return 1;
}
// 假设CheatEngine里的数值是相对于模块基址的偏移
uintptr_t goldAddr = moduleBase + 0x017EED8;
// 用goldAddr作为ReadProcessMemory的地址参数

4. 权限问题处理

  • 确保你的程序以管理员权限运行,否则可能无法打开游戏进程。
  • 不要用PROCESS_ALL_ACCESS权限,这个权限需要特殊系统权限,普通用户默认没有,用PROCESS_VM_READ足够完成内存读取。

常见错误码说明

  • 错误码5:权限不足,需管理员权限运行程序,或降低OpenProcess请求的权限。
  • 错误码299:32位程序访问64位进程内存,需切换到64位编译。
  • 错误码12B:地址无效,说明你使用的地址不是游戏进程的有效内存地址。

内容的提问来源于stack exchange,提问作者Noah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:42:45