Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何访问其他程序中的结构';什么是记忆?_C#_.net_C++_Memory_Struct - Fatal编程技术网

C# 如何访问其他程序中的结构';什么是记忆?

C# 如何访问其他程序中的结构';什么是记忆?,c#,.net,c++,memory,struct,C#,.net,C++,Memory,Struct,我知道如何导入和使用C#中的读/写过程。 我在做游戏教练。我需要“直接”访问浇铸到struct的其他进程内存。我可以使用readprocessmemory或writeprocessmemory,但对于许多结构来说,这需要花费很多时间来输入 C++中有这样的结构: class CRenderer { public: char unknown0[1692]; //0x0000 BYTE ID07D54FC8; //0x069C BYTE drawObjects; //0x

我知道如何导入和使用C#中的读/写过程。 我在做游戏教练。我需要“直接”访问浇铸到struct的其他进程内存。我可以使用readprocessmemory或writeprocessmemory,但对于许多结构来说,这需要花费很多时间来输入

C++中有这样的结构:

class CRenderer
{
public:
    char unknown0[1692]; //0x0000
    BYTE ID07D54FC8; //0x069C  
    BYTE drawObjects; //0x069D  
    BYTE drawDeferred; //0x069E  
    BYTE drawParticles; //0x069F  
    BYTE ID07E1CA70; //0x06A0  
    BYTE drawBundledMeshes; //0x06A1  
    BYTE drawStaticMeshes; //0x06A2  
    BYTE drawSkinnedMeshes; //0x06A3  
    BYTE drawRoads; //0x06A4  
    BYTE drawTerrain; //0x06A5  
    BYTE drawUnderGrowth; //0x06A6  
    BYTE drawOverGrowth; //0x06A7  
    BYTE drawNameTags; //0x06A8  
    BYTE drawTrees; //0x06A9  
    BYTE ID07E1CE70; //0x06AA  
    BYTE ID07E1CDF0; //0x06AB  
    BYTE DrawFPS; //0x06AC  
    BYTE ID07E1CEF0; //0x06AD  
    BYTE ID07E1C8F0; //0x06AE  
    BYTE ID07E1C870; //0x06AF  
    BYTE drawGraphs; //0x06B0  
    BYTE ID07D55048; //0x06B1  
    BYTE drawSkyDome; //0x06B2  
    BYTE drawSunFlare; //0x06B3  
    BYTE drawPostProduction; //0x06B4  
    BYTE ID07D550C8; //0x06B5  
    char unknown1718[6534]; //0x06B6
};//Size=0x203C(8252)
如何用C#表示该结构? 实现这样的目标最简单的方法是什么:

//C++
DWORD RendererBase = (DWORD)GetModuleHandle( "RendDx9.dll" ); //Gets the base address of RenDX9.dll
DWORD RendererOffset = RendererBase + 0x23D098; //Static address
CRenderer *cRenderer = *(CRenderer**)RendererOffset; //Points to the class using the static offset

cRenderer->drawSkyDome = 0; //No Sky
cRenderer->DrawFPS = 1; //Show FPS
cRenderer.drawSkyDome = 0; //No Sky
cRenderer.DrawFPS = 1; //Show FPS
在C#中,我希望能够像这样使用它:

//C++
DWORD RendererBase = (DWORD)GetModuleHandle( "RendDx9.dll" ); //Gets the base address of RenDX9.dll
DWORD RendererOffset = RendererBase + 0x23D098; //Static address
CRenderer *cRenderer = *(CRenderer**)RendererOffset; //Points to the class using the static offset

cRenderer->drawSkyDome = 0; //No Sky
cRenderer->DrawFPS = 1; //Show FPS
cRenderer.drawSkyDome = 0; //No Sky
cRenderer.DrawFPS = 1; //Show FPS

如何在我的C#应用程序中将其他进程内存用作结构?

如果需要与非托管程序二进制兼容的结构,可以使用
[StructLayout]
属性及其好友。例如,在您的情况下,它将类似于:

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RendererData
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1692)]
    public byte[] Unknown;
    public byte ID07D54FC8;
    public byte DrawObjects;
    public byte DrawDeferred;
    // ...
    public byte DrawFPS;
    // ...
    public byte DrawSkyDome;
    // ...
}

void Main()
{
    IntPtr rendererBase = GetModuleHandle("RendDx9.dll");
    if (rendererBase == IntPtr.Zero)
    {
        throw new InvalidOperationException("RendDx9.dll not found");
    }
    IntPtr rendererAddr = IntPtr.Add(rendererBase, 0x23D098);

    var data = new RendererData();
    Marshal.PtrToStructure(rendererAddr, data);

    data.DrawSkyDome = 0;
    data.DrawFPS = 1;

    Marshal.StructureToPtr(data, rendererAddr, false);
}

我不确定您是否能够以这种直接方式访问另一个模块的数据,但您可以用
ReadProcessMemory
/
WriteProcessMemory
替换该方法,基本原则仍然成立(只是这一次,您需要为结构管理内存).

如果要读取或写入由不同进程拥有的内存,则需要使用
ReadProcessMemory
WriteProcessMemory
。这是唯一的办法

对于您正在尝试执行的操作,将内存值写入另一个进程是不够的。您可能还需要调用一些方法。如果要修改的这些变量是属性,则需要调用属性访问方法。如果变量包含动态内容(例如列表、字符串),则
WriteProcessMemory
无法完成任务

这类事情通常是通过定义良好的接口(和API)、某种插件架构等来完成的