C#调用kernel32.dll的ReadProcessMemory在Windows11返回错误299
解决Windows 11下ReadProcessMemory返回错误299(ERROR_PARTIAL_COPY)的问题
错误299对应ERROR_PARTIAL_COPY,表示尝试读取的内存中存在无法访问的区域。结合你Win10正常、Win11异常的情况,核心原因大概率是Windows 11的安全机制限制或进程句柄权限不足,以下是具体排查和解决方法:
1. 确保进程句柄拥有足够权限
默认通过Process.Handle获取的进程句柄,权限可能不包含完整的内存读取权限。建议手动调用OpenProcess函数,明确请求PROCESS_VM_READ和PROCESS_QUERY_INFORMATION权限:
修改后的PInvoke代码
// 新增OpenProcess和CloseHandle的PInvoke声明 [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenProcess( uint dwDesiredAccess, bool bInheritHandle, int dwProcessId ); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); // 权限常量定义 const uint PROCESS_VM_READ = 0x0010; const uint PROCESS_QUERY_INFORMATION = 0x0400; // 原有的ReadProcessMemory声明保持不变 [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ReadProcessMemory( [In] IntPtr hProcess, [In] IntPtr lpBaseAddress, [Out] byte[] lpBuffer, [In] UIntPtr dwSize, [Out] out UIntPtr lpNumberOfBytesRead );
使用方式
int targetProcessId = 1234; // 替换为目标进程ID IntPtr hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, targetProcessId); if (hProcess != IntPtr.Zero) { byte[] buffer = new byte[4]; UIntPtr bytesRead; bool success = ReadProcessMemory(hProcess, targetAddress, buffer, (UIntPtr)buffer.Length, out bytesRead); if (!success) { int errorCode = Marshal.GetLastWin32Error(); // 处理错误 } // 用完必须关闭句柄 CloseHandle(hProcess); } else { int errorCode = Marshal.GetLastWin32Error(); // 处理打开进程失败的错误 }
2. 检查Windows 11内存完整性设置
Windows 11默认开启内存完整性(属于Windows Defender核心隔离功能),该功能会严格限制跨进程内存读取操作,尤其是针对受保护的系统进程或签名进程:
- 打开「设置」→「隐私和安全性」→「Windows安全中心」→「设备安全性」→「核心隔离详细信息」
- 临时关闭「内存完整性」选项,重启系统后测试程序是否正常运行
- 若关闭后恢复正常,说明是该安全机制导致,长期解决方案需调整程序适配(如避免读取受保护进程内存)
3. 验证进程位数兼容性
如果你的程序是32位,而目标进程是64位(或反之),跨位数内存读取可能导致地址解析错误,触发ERROR_PARTIAL_COPY:
- 在项目属性中设置程序的目标平台为
x64或x86,与目标进程位数保持一致 - 避免使用
Any CPU模式,防止运行时位数不匹配
4. 确认目标内存地址有效性
错误299也可能是因为你尝试读取的内存地址本身无效(如已被释放、不属于目标进程的内存空间):
- 先通过
VirtualQueryEx函数验证目标地址是否属于目标进程的有效内存区域 - 确保读取的内存范围未超出目标进程的可用地址空间
内容的提问来源于stack exchange,提问作者isomania
相关产品推荐
相关产品推荐

