返回提交历史
Modified
XFEExtension.NetCore.MemoryEditor/MemoryEditor.cs
+26
-0
Added
XFEExtension.NetCore.MemoryEditor/MemoryListener.cs
+130
-0
XFEstudio/XFEExtension.NetCore.MemoryEditor
添加监听器功能
7d2b0a8
代码差异
2 个文件
+156
-0
@@ -1,4 +1,5 @@
1
1
using System.Diagnostics;
2
using System.Net;
2
3
using System.Runtime.InteropServices;
3
4
using XFEExtension.NetCore.DelegateExtension;
4
5
@@ -22,6 +23,10 @@ public partial class MemoryEditor
22
23
/// </summary>
23
24
public nint ProcessHandle { get; set; }
24
25
/// <summary>
26
/// 内存监听器
27
/// </summary>
28
public MemoryListener Listener { get; set; }
29
/// <summary>
25
30
/// 进程位数类型(32/64)
26
31
/// </summary>
27
32
public ProcessType ProcessBiteType { get; set; }
@@ -40,6 +45,21 @@ public partial class MemoryEditor
40
45
/// <param name="source">待写入值</param>
41
46
public void WriteMemory<T>(nint address, T source) where T : struct => WriteMemory<T>(ProcessHandle, address, source);
42
47
/// <summary>
48
/// 添加监听器
49
/// </summary>
50
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
51
/// <param name="address">待监听的内存地址</param>
52
public void AddListener<T>(nint address) where T : struct => _ = Listener.StartListen<T>(address);
53
/// <summary>
54
/// 移除并停止指定监听器
55
/// </summary>
56
/// <param name="address">监听地址</param>
57
public void RemoveListener(nint address) => Listener.StopListener(address);
58
/// <summary>
59
/// 移除所有监听器
60
/// </summary>
61
public void RemoveListeners()=> Listener.StopListener();
62
/// <summary>
43
63
/// 解析基址对应的实际地址
44
64
/// </summary>
45
65
/// <param name="moduleName">模块名称(基址的进程部分,可以是DLL等)</param>
@@ -58,6 +78,8 @@ public partial class MemoryEditor
58
78
TargetProcess = process;
59
79
ProcessHandle = GetProcessHandle(TargetProcess.Id, processAccessFlags);
60
80
ProcessBiteType = processType;
81
Listener = new(ProcessHandle);
82
Listener.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e);
61
83
}
62
84
/// <summary>
63
85
/// 内存编辑器
@@ -70,6 +92,8 @@ public partial class MemoryEditor
70
92
TargetProcess = Process.GetProcessesByName(processName).First();
71
93
ProcessHandle = GetProcessHandle(TargetProcess.Id, processAccessFlags);
72
94
ProcessBiteType = processType;
95
Listener = new(ProcessHandle);
96
Listener.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e);
73
97
}
74
98
/// <summary>
75
99
/// 内存编辑器
@@ -82,6 +106,8 @@ public partial class MemoryEditor
82
106
TargetProcess = Process.GetProcessById(processId);
83
107
ProcessHandle = GetProcessHandle(TargetProcess.Id, processAccessFlags);
84
108
ProcessBiteType = processType;
109
Listener = new(ProcessHandle);
110
Listener.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e);
85
111
}
86
112
#region 静态方法
87
113
/// <summary>
@@ -0,0 +1,130 @@
1
using XFEExtension.NetCore.DelegateExtension;
2
3
namespace XFEExtension.NetCore.MemoryEditor;
4
5
/// <summary>
6
/// 内存监听器
7
/// </summary>
8
public class MemoryListener : IDisposable
9
{
10
private bool disposedValue;
11
private readonly Dictionary<nint, bool> listeningList = [];
12
/// <summary>
13
/// 当监听值发生改变时触发
14
/// </summary>
15
public event XFEEventHandler<nint, object>? ValueChanged;
16
/// <summary>
17
/// 进程句柄
18
/// </summary>
19
public nint ProcessHandler { get; set; }
20
/// <summary>
21
/// 是否启用监听
22
/// </summary>
23
public bool IsListening { get; set; }
24
/// <summary>
25
/// 开始监听
26
/// </summary>
27
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
28
/// <param name="memoryAddress">待监听的内存地址</param>
29
/// <returns></returns>
30
public async Task StartListen<T>(nint memoryAddress) where T : struct
31
{
32
IsListening = true;
33
listeningList.Add(memoryAddress, true);
34
await Task.Run(() =>
35
{
36
var lastValue = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress);
37
while (listeningList[memoryAddress] && IsListening)
38
{
39
var currentValue = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress);
40
if (!currentValue.Equals(lastValue))
41
{
42
ValueChanged?.Invoke(ProcessHandler, currentValue);
43
currentValue = lastValue;
44
}
45
}
46
listeningList.Remove(memoryAddress);
47
});
48
}
49
/// <summary>
50
/// 开始监听
51
/// </summary>
52
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
53
/// <param name="memoryAddress">待监听的内存地址</param>
54
/// <param name="delay">检测频率,以毫秒为单位</param>
55
/// <returns></returns>
56
public async Task StartListen<T>(nint memoryAddress, int delay = 10) where T : struct
57
{
58
IsListening = true;
59
listeningList.Add(memoryAddress, true);
60
await Task.Run(() =>
61
{
62
var lastValue = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress);
63
while (listeningList[memoryAddress] && IsListening)
64
{
65
var currentValue = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress);
66
if (!currentValue.Equals(lastValue))
67
{
68
ValueChanged?.Invoke(ProcessHandler, currentValue);
69
currentValue = lastValue;
70
}
71
Thread.Sleep(delay);
72
}
73
listeningList.Remove(memoryAddress);
74
});
75
}
76
/// <summary>
77
/// 停止所有监听
78
/// </summary>
79
public void StopListener() => IsListening = false;
80
/// <summary>
81
/// 停止指定进程的监听
82
/// </summary>
83
/// <param name="memoryAddress"></param>
84
public void StopListener(nint memoryAddress) => listeningList[memoryAddress] = false;
85
/// <summary>
86
/// 内存监听器
87
/// </summary>
88
/// <param name="processName">进程名称</param>
89
public MemoryListener(string processName) => ProcessHandler = MemoryEditor.GetProcessHandle(processName, ProcessAccessFlags.All);
90
/// <summary>
91
/// 内存监听器
92
/// </summary>
93
/// <param name="processHandler">进程句柄</param>
94
public MemoryListener(nint processHandler) => ProcessHandler = processHandler;
95
/// <summary>
96
/// 释放资源
97
/// </summary>
98
/// <param name="disposing"></param>
99
protected virtual void Dispose(bool disposing)
100
{
101
if (!disposedValue)
102
{
103
if (disposing)
104
{
105
IsListening = false;
106
}
107
108
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
109
// TODO: 将大型字段设置为 null
110
disposedValue = true;
111
}
112
}
113
114
// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
115
// ~MemoryListener()
116
// {
117
// // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
118
// Dispose(disposing: false);
119
// }
120
121
/// <summary>
122
/// 释放资源
123
/// </summary>
124
public void Dispose()
125
{
126
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
127
Dispose(disposing: true);
128
GC.SuppressFinalize(this);
129
}
130
}