XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.MemoryEditor

【DLL】内存读写工具/编辑器

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension.NetCore.MemoryEditor

将监听器分类为动态和静态

f31902e
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

11 个文件 +538 -226
Added XFEExtension.NetCore.MemoryEditor/DynamicMemoryListener.cs +63 -0
@@ -0,0 +1,63 @@
1 using XFEExtension.NetCore.ImplExtension;
2
3 namespace XFEExtension.NetCore.MemoryEditor;
4
5 /// <summary>
6 /// 内存动态监听器
7 /// </summary>
8 /// <param name="customName">监听器自定义标识名</param>
9 /// <param name="getAddressFunc">获取内存的动态方法</param>
10 /// <param name="memoryAddressType">内存地址数据类型</param>
11 [CreateImpl]
12 public abstract class DynamicMemoryListener(string customName, Func<nint?> getAddressFunc, Type memoryAddressType) : MemoryListener(customName, memoryAddressType)
13 {
14 private readonly Func<nint?> getAddressFunc = getAddressFunc;
15 /// <summary>
16 /// 获取目标内存地址方法
17 /// </summary>
18 public Func<nint?> GetAddressFunc { get => getAddressFunc; }
19 /// <summary>
20 /// 开始监听
21 /// </summary>
22 /// <param name="processHandler">监听的进程句柄</param>
23 /// <param name="frequency">监听检测频率</param>
24 /// <returns></returns>
25 public override async Task StartListen(nint processHandler, TimeSpan frequency)
26 {
27 await base.StartListen(processHandler, frequency);
28 CurrentListeningTask = Task.Run(async () =>
29 {
30 var memoryAddress = getAddressFunc.Invoke();
31 object? lastValue = null;
32 if (memoryAddress is not null)
33 try { lastValue = MemoryEditor.ReadMemory(processHandler, memoryAddress.Value, memoryAddressType); } catch { }
34 while (isListening)
35 {
36 try
37 {
38 memoryAddress = getAddressFunc.Invoke();
39 if (memoryAddress == 0)
40 {
41 if (lastValue is not null)
42 valueChanged?.Invoke(this, new(lastValue is not null, false, lastValue, null, name));
43 lastValue = null;
44 while (memoryAddress == 0 && isListening)
45 {
46 memoryAddress = getAddressFunc.Invoke();
47 await Task.Delay(frequency);
48 }
49 }
50 var currentValue = MemoryEditor.ReadMemory(processHandler, memoryAddress!.Value, memoryAddressType);
51 if (lastValue is null == currentValue is null || lastValue?.Equals(currentValue) == false)
52 {
53 valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, customName));
54 lastValue = currentValue;
55 }
56 await Task.Delay(frequency);
57 }
58 catch { }
59 }
60 });
61 await CurrentListeningTask;
62 }
63 }
Renamed XFEExtension.NetCore.MemoryEditor/Manager/DynamicMemoryManager.cs +2 -7
@@ -5,9 +5,9 @@ namespace XFEExtension.NetCore.MemoryEditor.Manager;
5 5 /// <summary>
6 6 /// 动态内存管理器
7 7 /// </summary>
8 public abstract class DynamicManager : MemoryManager
8 public abstract class DynamicMemoryManager : MemoryManager
9 9 {
10 internal DynamicManager(nint processHandler) : base(processHandler)
10 internal DynamicMemoryManager(nint processHandler) : base(processHandler)
11 11 {
12 12 }
13 13 /// <summary>
@@ -34,11 +34,6 @@ public abstract class DynamicManager : MemoryManager
34 34 /// <returns></returns>
35 35 public override IEnumerator GetEnumerator() => memoryAddressGetFuncDictionary.Values.GetEnumerator();
36 36 /// <summary>
37 /// 释放资源
38 /// </summary>
39 /// <param name="disposing"></param>
40 protected override void Dispose(bool disposing) => base.Dispose(disposing);
41 /// <summary>
42 37 /// 移除指定名称的地址
43 38 /// </summary>
44 39 /// <param name="addressName">地址标识名称</param>
Modified XFEExtension.NetCore.MemoryEditor/Manager/MemoryItem.cs +6 -2
@@ -3,8 +3,12 @@
3 3 /// <summary>
4 4 /// 内存条目
5 5 /// </summary>
6 public abstract class MemoryItem(string name)
6 /// <typeparam name="T">地址类型</typeparam>
7 /// <param name="name">名称</param>
8 /// <param name="memoryListener">监听器</param>
9 public abstract class MemoryItem<T>(string name, MemoryListenerManager memoryListener)
7 10 {
11 private protected MemoryListenerManager memoryListener = memoryListener;
8 12 /// <summary>
9 13 /// 内存地址标识名
10 14 /// </summary>
@@ -20,7 +24,7 @@ public abstract class MemoryItem(string name)
20 24 /// <summary>
21 25 /// 该地址是否存在监听器
22 26 /// </summary>
23 public bool HasListener { get; set; }
27 public bool HasListener { get; protected set; }
24 28 /// <summary>
25 29 /// 添加监听器
26 30 /// </summary>
Added XFEExtension.NetCore.MemoryEditor/Manager/MemoryListenerManager.cs +296 -0
@@ -0,0 +1,296 @@
1 using System.Collections;
2 using System.Diagnostics;
3 using XFEExtension.NetCore.DelegateExtension;
4
5 namespace XFEExtension.NetCore.MemoryEditor.Manager;
6
7 /// <summary>
8 /// 内存监听器
9 /// </summary>
10 public class MemoryListenerManager : IDisposable, IEnumerable
11 {
12 private bool disposedValue;
13 private readonly List<nint> addressListToListen = [];
14 private readonly Dictionary<string, Func<nint?>> addressFuncDictionaryToListen = [];
15 private readonly Dictionary<nint, bool> listeningAddressDictionary = [];
16 private readonly Dictionary<string, bool> listeningAddressFuncDictionary = [];
17 /// <summary>
18 /// 当监听值发生改变时触发
19 /// </summary>
20 public event XFEEventHandler<MemoryValue>? ValueChanged;
21 /// <summary>
22 /// 当前进程结束时触发
23 /// </summary>
24 public event EventHandler? CurrentProcessExit;
25 /// <summary>
26 /// 进程句柄
27 /// </summary>
28 public nint ProcessHandler { get; set; }
29 private Process? currentProcess;
30 /// <summary>
31 /// 当前监听内存的目标进程
32 /// </summary>
33 public Process? CurrentProcess
34 {
35 get { return currentProcess; }
36 set
37 {
38 if (value is not null)
39 {
40 currentProcess?.Dispose();
41 currentProcess = value;
42 ProcessHandler = MemoryEditor.GetProcessHandle(value.Id, ProcessAccessFlags.All);
43 isCurrentProcessRunning = true;
44 currentProcess.Exited += (sender, e) => CurrentProcessExit?.Invoke(sender, e);
45 foreach (var address in addressListToListen)
46 {
47
48 }
49 }
50 }
51 }
52 /// <summary>
53 /// 是否启用监听
54 /// </summary>
55 public bool IsListening { get; set; }
56 /// <summary>
57 /// 开始监听
58 /// </summary>
59 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
60 /// <param name="memoryAddress">待监听的内存地址</param>
61 /// <param name="customName">自定义监听器标识名</param>
62 /// <returns></returns>
63 public async Task StartListen<T>(nint memoryAddress, string? customName = null) where T : struct
64 {
65 IsListening = true;
66 await Task.Run(() =>
67 {
68 bool lastSuccess = false;
69 var lastValue = default(T);
70 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress, out lastValue); } catch { }
71 addressListToListen.Add(memoryAddress);
72 listeningAddressDictionary.Add(memoryAddress, true);
73 ReStart:
74 try
75 {
76 while (listeningAddressDictionary[memoryAddress] && IsListening && isCurrentProcessRunning)
77 {
78 try
79 {
80 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress, out var currentValue);
81 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
82 {
83 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
84 lastValue = currentValue;
85 lastSuccess = currentSuccess;
86 }
87 }
88 catch { }
89 }
90 listeningAddressDictionary.Remove(memoryAddress);
91 }
92 catch
93 {
94 goto ReStart;
95 }
96 });
97 }
98 /// <summary>
99 /// 开始监听
100 /// </summary>
101 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
102 /// <param name="memoryAddress">待监听的内存地址</param>
103 /// <param name="delay">检测频率,以毫秒为单位</param>
104 /// <param name="customName">自定义监听器标识名</param>
105 /// <returns></returns>
106 public async Task StartListen<T>(nint memoryAddress, int delay, string? customName = null) where T : struct => await StartListen<T>(memoryAddress, TimeSpan.FromMilliseconds(delay), customName);
107 /// <summary>
108 /// 开始监听
109 /// </summary>
110 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
111 /// <param name="memoryAddress">待监听的内存地址</param>
112 /// <param name="delay">检测频率</param>
113 /// <param name="customName">自定义监听器标识名</param>
114 /// <returns></returns>
115 public async Task StartListen<T>(nint memoryAddress, TimeSpan delay, string? customName = null) where T : struct
116 {
117 IsListening = true;
118 await Task.Run(async () =>
119 {
120 bool lastSuccess = false;
121 var lastValue = default(T);
122 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress, out lastValue); } catch { }
123 addressListToListen.Add(memoryAddress);
124 listeningAddressDictionary.Add(memoryAddress, true);
125 ReStart:
126 try
127 {
128 while (listeningAddressDictionary[memoryAddress] && IsListening && isCurrentProcessRunning)
129 {
130 try
131 {
132 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress, out var currentValue);
133 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
134 {
135 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
136 lastValue = currentValue;
137 lastSuccess = currentSuccess;
138 }
139 await Task.Delay(delay);
140 }
141 catch { }
142 }
143 listeningAddressDictionary.Remove(memoryAddress);
144 }
145 catch
146 {
147 goto ReStart;
148 }
149 });
150 }
151 /// <summary>
152 /// 开始监听
153 /// </summary>
154 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
155 /// <param name="getMemoryAddressFunc">动态获取内存地址的方法</param>
156 /// <param name="delay">检测频率</param>
157 /// <param name="customName">自定义监听器标识名</param>
158 /// <returns></returns>
159 public async Task StartListen<T>(Func<nint?> getMemoryAddressFunc, int delay, string customName) where T : struct => await StartListen<T>(getMemoryAddressFunc, TimeSpan.FromMilliseconds(delay), customName);
160 /// <summary>
161 /// 开始监听
162 /// </summary>
163 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
164 /// <param name="getMemoryAddressFunc">动态获取内存地址的方法</param>
165 /// <param name="delay">检测频率</param>
166 /// <param name="customName">自定义监听器标识名</param>
167 /// <returns></returns>
168 public async Task StartListen<T>(Func<nint?> getMemoryAddressFunc, TimeSpan delay, string customName) where T : struct
169 {
170 IsListening = true;
171 await Task.Run(async () =>
172 {
173 var memoryAddress = getMemoryAddressFunc.Invoke();
174 bool lastSuccess = false;
175 var lastValue = default(T);
176 if (memoryAddress is not null)
177 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress.Value, out lastValue); } catch { }
178 addressFuncDictionaryToListen.Add(customName, getMemoryAddressFunc);
179 listeningAddressFuncDictionary.Add(customName, true);
180 ReStart:
181 try
182 {
183 while (listeningAddressFuncDictionary[customName] && IsListening && isCurrentProcessRunning)
184 {
185 try
186 {
187 memoryAddress = getMemoryAddressFunc.Invoke();
188 if (memoryAddress == 0)
189 {
190 if (lastSuccess)
191 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, false, lastValue, null, customName));
192 lastSuccess = false;
193 lastValue = default;
194 while (memoryAddress == 0 && listeningAddressFuncDictionary[customName] && IsListening && isCurrentProcessRunning)
195 {
196 memoryAddress = getMemoryAddressFunc.Invoke();
197 await Task.Delay(delay);
198 }
199 }
200 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress!.Value, out var currentValue);
201 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
202 {
203 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
204 lastValue = currentValue;
205 lastSuccess = currentSuccess;
206 }
207 await Task.Delay(delay);
208 }
209 catch { }
210 }
211 listeningAddressFuncDictionary.Remove(customName);
212 }
213 catch
214 {
215 goto ReStart;
216 }
217 });
218 }
219 /// <summary>
220 /// 停止所有监听
221 /// </summary>
222 public void StopListener()
223 {
224 IsListening = false;
225 addressListToListen.Clear();
226 addressFuncDictionaryToListen.Clear();
227 }
228 /// <summary>
229 /// 停止指定进程的监听
230 /// </summary>
231 /// <param name="memoryAddress">内存地址</param>
232 public void StopListener(nint memoryAddress)
233 {
234 listeningAddressDictionary[memoryAddress] = false;
235 addressListToListen.Remove(memoryAddress);
236 }
237 /// <summary>
238 /// 停止指定进程的监听
239 /// </summary>
240 /// <param name="customName">自定义名称</param>
241 public void StopListener(string customName)
242 {
243 listeningAddressFuncDictionary[customName] = false;
244 addressFuncDictionaryToListen.Remove(customName);
245 }
246 /// <summary>
247 /// 内存监听器
248 /// </summary>
249 public MemoryListenerManager() { }
250 /// <summary>
251 /// 内存监听器
252 /// </summary>
253 /// <param name="targetProcess">目标进程</param>
254 public MemoryListenerManager(Process targetProcess) => CurrentProcess = targetProcess;
255 /// <summary>
256 /// 内存监听器
257 /// </summary>
258 /// <param name="targetProcessId">目标进程ID</param>
259 public MemoryListenerManager(int targetProcessId) => CurrentProcess = Process.GetProcessById(targetProcessId);
260 /// <summary>
261 /// 内存监听器
262 /// </summary>
263 /// <param name="processName">进程名称</param>
264 public MemoryListenerManager(string processName) => CurrentProcess = Process.GetProcessesByName(processName).First();
265 /// <summary>
266 /// 释放资源
267 /// </summary>
268 /// <param name="disposing"></param>
269 protected virtual void Dispose(bool disposing)
270 {
271 if (!disposedValue)
272 {
273 if (disposing)
274 {
275 IsListening = false;
276 ValueChanged = null;
277 CurrentProcessExit = null;
278 }
279
280 disposedValue = true;
281 }
282 }
283 /// <summary>
284 /// 释放资源
285 /// </summary>
286 public void Dispose()
287 {
288 Dispose(disposing: true);
289 GC.SuppressFinalize(this);
290 }
291
292 public IEnumerator GetEnumerator()
293 {
294 throw new NotImplementedException();
295 }
296 }
Modified XFEExtension.NetCore.MemoryEditor/Manager/MemoryManager.cs +2 -2
@@ -13,7 +13,7 @@ public abstract class MemoryManager(nint processHandler) : IDisposable, IEnumera
13 13 /// <summary>
14 14 /// 监听器
15 15 /// </summary>
16 public MemoryListener Listener { get; protected set; } = new(processHandler);
16 public MemoryListenerManager Listener { get; protected set; } = new(processHandler);
17 17 /// <summary>
18 18 /// 现成句柄
19 19 /// </summary>
@@ -46,7 +46,7 @@ public abstract class MemoryManager(nint processHandler) : IDisposable, IEnumera
46 46 /// 释放资源
47 47 /// </summary>
48 48 /// <param name="disposing"></param>
49 protected virtual void Dispose(bool disposing)
49 private protected virtual void Dispose(bool disposing)
50 50 {
51 51 if (!disposedValue)
52 52 {
Modified XFEExtension.NetCore.MemoryEditor/Manager/StaticMemoryItem.cs +8 -1
@@ -4,11 +4,18 @@ public abstract class StaticMemoryItem(string name) : MemoryItem(name)
4 4 {
5 5 public override void AddListener()
6 6 {
7
7 if (HasListener)
8 throw new InvalidOperationException("已存在监听器,无法重复添加");
9 HasListener = true;
10 memoryListener.StartListen
8 11 }
9 12
10 13 public override void RemoveListener()
11 14 {
12 15 throw new NotImplementedException();
13 16 }
17 public void UpdateStaticAddress()
18 {
19
20 }
14 21 }
Renamed XFEExtension.NetCore.MemoryEditor/Manager/StaticMemoryManager.cs +2 -7
@@ -5,9 +5,9 @@ namespace XFEExtension.NetCore.MemoryEditor.Manager;
5 5 /// <summary>
6 6 /// 静态内存管理器
7 7 /// </summary>
8 public abstract class StaticManager : MemoryManager
8 public abstract class StaticMemoryManager : MemoryManager
9 9 {
10 internal StaticManager(nint processHandler) : base(processHandler)
10 internal StaticMemoryManager(nint processHandler) : base(processHandler)
11 11 {
12 12 }
13 13
@@ -61,11 +61,6 @@ public abstract class StaticManager : MemoryManager
61 61 /// <summary>
62 62 /// 释放资源
63 63 /// </summary>
64 /// <param name="disposing"></param>
65 protected override void Dispose(bool disposing) => base.Dispose(disposing);
66 /// <summary>
67 /// 释放资源
68 /// </summary>
69 64 /// <param name="addressName">地址标识名称</param>
70 65 public override void Remove(string addressName)
71 66 {
Modified XFEExtension.NetCore.MemoryEditor/MemoryEditor.cs +29 -18
@@ -10,7 +10,6 @@ namespace XFEExtension.NetCore.MemoryEditor;
10 10 public partial class MemoryEditor : IDisposable
11 11 {
12 12 private bool disposedValue;
13
14 13 /// <summary>
15 14 /// 当指定地址的内存值变化时触发
16 15 /// </summary>
@@ -26,7 +25,7 @@ public partial class MemoryEditor : IDisposable
26 25 /// <summary>
27 26 /// 内存监听器
28 27 /// </summary>
29 public MemoryListener Listener { get; set; }
28 public MemoryListenerManager Listener { get; set; }
30 29 /// <summary>
31 30 /// 进程位数类型(32/64)
32 31 /// </summary>
@@ -170,26 +169,14 @@ public partial class MemoryEditor : IDisposable
170 169 {
171 170 Listener.Dispose();
172 171 }
173
174 // TODO: 释放未托管的资源(未托管的对象)并重写终结器
175 // TODO: 将大型字段设置为 null
176 172 disposedValue = true;
177 173 }
178 174 }
179
180 // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
181 // ~MemoryEditor()
182 // {
183 // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
184 // Dispose(disposing: false);
185 // }
186
187 175 /// <summary>
188 176 /// 释放资源
189 177 /// </summary>
190 178 public void Dispose()
191 179 {
192 // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
193 180 Dispose(disposing: true);
194 181 GC.SuppressFinalize(this);
195 182 }
@@ -239,6 +226,30 @@ public partial class MemoryEditor : IDisposable
239 226 }
240 227 }
241 228 /// <summary>
229 /// 读取指定地址的内存<br/>
230 /// 如非有意使用,请转到<seealso cref="ReadMemory{T}(nint, nint, out T)"/>
231 /// </summary>
232 /// <param name="processHandle">进程句柄</param>
233 /// <param name="address">指定地址</param>
234 /// <param name="type">目标类型(int,float,long等)</param>
235 /// <returns>读取结果</returns>
236 public static object? ReadMemory(nint processHandle, nint address, Type type)
237 {
238 unsafe
239 {
240 var size = Marshal.SizeOf(type);
241 var buffer = new byte[size];
242 if (ReadProcessMemory(processHandle, address, buffer, (uint)size, out _))
243 {
244 fixed (byte* pBuffer = buffer)
245 {
246 return Marshal.PtrToStructure((nint)pBuffer, type);
247 }
248 }
249 return null;
250 }
251 }
252 /// <summary>
242 253 /// 在指定内存中写入数据
243 254 /// </summary>
244 255 /// <typeparam name="T">数据类型(int,float,long等)</typeparam>
@@ -275,24 +286,24 @@ public partial class MemoryEditor : IDisposable
275 286 var resolvedAddress = nint.Add(moduleBaseAddress, baseAddress);
276 287 if (processType == ProcessType.Bit32)
277 288 {
278 foreach (int offset in offsets)
289 foreach (nint offset in offsets)
279 290 {
280 291 var success = ReadMemory(process.Handle, resolvedAddress, out int nextAddress);
281 292 if (!success || nextAddress == nint.Zero)
282 293 return nint.Zero;
283 294 var pointerValue = new nint(nextAddress);
284 resolvedAddress = nint.Add(pointerValue, offset);
295 resolvedAddress = pointerValue + offset;
285 296 }
286 297 }
287 298 else
288 299 {
289 foreach (int offset in offsets)
300 foreach (nint offset in offsets)
290 301 {
291 302 var success = ReadMemory(process.Handle, resolvedAddress, out long nextAddress);
292 303 if (!success || nextAddress == nint.Zero)
293 304 return nint.Zero;
294 305 var pointerValue = new nint(nextAddress);
295 resolvedAddress = nint.Add(pointerValue, offset);
306 resolvedAddress = pointerValue + offset;
296 307 }
297 308 }
298 309 return resolvedAddress;
Modified XFEExtension.NetCore.MemoryEditor/MemoryListener.cs +75 -188
@@ -1,245 +1,132 @@
1 using System.Diagnostics;
2 using XFEExtension.NetCore.DelegateExtension;
1 using XFEExtension.NetCore.DelegateExtension;
3 2
4 3 namespace XFEExtension.NetCore.MemoryEditor;
5 4
6 5 /// <summary>
7 6 /// 内存监听器
8 7 /// </summary>
9 public class MemoryListener : IDisposable
8 /// <param name="customName">监听器自定义标识名</param>
9 /// <param name="memoryAddressType">内存地址类型</param>
10 public abstract class MemoryListener(string customName, Type memoryAddressType) : IDisposable
10 11 {
11 private bool disposedValue;
12 private readonly Dictionary<nint, bool> listeningList = [];
13 private readonly Dictionary<string, bool> listeningFuncList = [];
12 private protected bool disposedValue;
13 private protected bool isListening;
14 private protected XFEEventHandler<MemoryListener, MemoryValue>? valueChanged;
14 15 /// <summary>
15 16 /// 当监听值发生改变时触发
16 17 /// </summary>
17 public event XFEEventHandler<nint?, MemoryValue>? ValueChanged;
18 public event XFEEventHandler<MemoryListener, MemoryValue>? ValueChanged
19 {
20 add => valueChanged += value;
21 remove => valueChanged -= value;
22 }
23 private protected string name = customName;
18 24 /// <summary>
19 /// 进程句柄
25 /// 监听器自定义标识名
20 26 /// </summary>
21 public nint ProcessHandler { get; set; }
27 public string Name
28 {
29 get { return name; }
30 set { name = value; }
31 }
32 private protected Type memoryAddressType = memoryAddressType;
22 33 /// <summary>
23 /// 是否启用监听
34 /// 内存地址类型
24 35 /// </summary>
25 public bool IsListening { get; set; }
36 public Type MemoryAddressType
37 {
38 get { return memoryAddressType; }
39 set { memoryAddressType = value; }
40 }
26 41 /// <summary>
27 /// 开始监听
42 /// 是否正在监听
28 43 /// </summary>
29 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
30 /// <param name="memoryAddress">待监听的内存地址</param>
31 /// <param name="customName">自定义监听器标识名</param>
32 /// <returns></returns>
33 public async Task StartListen<T>(nint memoryAddress, string? customName = null) where T : struct
44 public bool IsListening
34 45 {
35 IsListening = true;
36 await Task.Run(() =>
37 {
38 bool lastSuccess = false;
39 var lastValue = default(T);
40 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress, out lastValue); } catch { }
41 listeningList.Add(memoryAddress, true);
42 ReStart:
43 try
44 {
45 while (listeningList[memoryAddress] && IsListening)
46 {
47 try
48 {
49 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress, out var currentValue);
50 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
51 {
52 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
53 lastValue = currentValue;
54 lastSuccess = currentSuccess;
55 }
56 }
57 catch { }
58 }
59 listeningList.Remove(memoryAddress);
60 }
61 catch
62 {
63 goto ReStart;
64 }
65 });
46 get { return isListening; }
47 set { isListening = value; }
66 48 }
49 private protected nint processHandler;
67 50 /// <summary>
68 /// 开始监听
51 /// 当前进程句柄
69 52 /// </summary>
70 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
71 /// <param name="memoryAddress">待监听的内存地址</param>
72 /// <param name="delay">检测频率,以毫秒为单位</param>
73 /// <param name="customName">自定义监听器标识名</param>
74 /// <returns></returns>
75 public async Task StartListen<T>(nint memoryAddress, int delay, string? customName = null) where T : struct => await StartListen<T>(memoryAddress, TimeSpan.FromMilliseconds(delay), customName);
53 public nint ProcessHandler { get => processHandler; }
54 /// <summary>
55 /// 当前的监听线程
56 /// </summary>
57 public Task? CurrentListeningTask { get; set; }
76 58 /// <summary>
77 59 /// 开始监听
78 60 /// </summary>
79 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
80 /// <param name="memoryAddress">待监听的内存地址</param>
81 /// <param name="delay">检测频率</param>
82 /// <param name="customName">自定义监听器标识名</param>
61 /// <param name="processHandler">进程句柄</param>
62 /// <param name="frequency">监听检测频率</param>
83 63 /// <returns></returns>
84 public async Task StartListen<T>(nint memoryAddress, TimeSpan delay, string? customName = null) where T : struct
64 /// <exception cref="InvalidOperationException">监听已启动,无法重复启动监听</exception>
65 public virtual async Task StartListen(nint processHandler, TimeSpan frequency)
85 66 {
86 IsListening = true;
87 await Task.Run(async () =>
88 {
89 bool lastSuccess = false;
90 var lastValue = default(T);
91 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress, out lastValue); } catch { }
92 listeningList.Add(memoryAddress, true);
93 ReStart:
94 try
95 {
96 while (listeningList[memoryAddress] && IsListening)
97 {
98 try
99 {
100 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress, out var currentValue);
101 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
102 {
103 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
104 lastValue = currentValue;
105 lastSuccess = currentSuccess;
106 }
107 await Task.Delay(delay);
108 }
109 catch { }
110 }
111 listeningList.Remove(memoryAddress);
112 }
113 catch
114 {
115 goto ReStart;
116 }
117 });
67 if (isListening)
68 throw new InvalidOperationException("监听已启动,无法重复启动监听");
69 isListening = true;
70 this.processHandler = processHandler;
71 await Task.CompletedTask;
118 72 }
119 73 /// <summary>
120 74 /// 开始监听
121 75 /// </summary>
122 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
123 /// <param name="getMemoryAddressFunc">动态获取内存地址的方法</param>
124 /// <param name="delay">检测频率</param>
125 /// <param name="customName">自定义监听器标识名</param>
76 /// <param name="processHandler">进程句柄</param>
77 /// <param name="frequency">监听检测频率</param>
126 78 /// <returns></returns>
127 public async Task StartListen<T>(Func<nint?> getMemoryAddressFunc, int delay, string customName) where T : struct => await StartListen<T>(getMemoryAddressFunc, TimeSpan.FromMilliseconds(delay), customName);
79 /// <exception cref="InvalidOperationException">监听已启动,无法重复启动监听</exception>
80 public async Task StartListen(nint processHandler, int frequency = 1) => await StartListen(processHandler, TimeSpan.FromMilliseconds(frequency));
128 81 /// <summary>
129 /// 开始监听
82 /// 停止监听
130 83 /// </summary>
131 /// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
132 /// <param name="getMemoryAddressFunc">动态获取内存地址的方法</param>
133 /// <param name="delay">检测频率</param>
134 /// <param name="customName">自定义监听器标识名</param>
135 84 /// <returns></returns>
136 public async Task StartListen<T>(Func<nint?> getMemoryAddressFunc, TimeSpan delay, string customName) where T : struct
85 public async Task StopListen()
137 86 {
138 IsListening = true;
139 await Task.Run(async () =>
140 {
141 var memoryAddress = getMemoryAddressFunc.Invoke();
142 bool lastSuccess = false;
143 var lastValue = default(T);
144 if (memoryAddress is not null)
145 try { lastSuccess = MemoryEditor.ReadMemory(ProcessHandler, memoryAddress.Value, out lastValue); } catch { }
146 listeningFuncList.Add(customName, true);
147 ReStart:
148 try
149 {
150 while (listeningFuncList[customName] && IsListening)
151 {
152 try
153 {
154 memoryAddress = getMemoryAddressFunc.Invoke();
155 if (memoryAddress == 0)
156 {
157 if (lastSuccess)
158 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, false, lastValue, null, customName));
159 lastSuccess = false;
160 lastValue = default;
161 while (memoryAddress == 0 && listeningFuncList[customName] && IsListening)
162 {
163 memoryAddress = getMemoryAddressFunc.Invoke();
164 await Task.Delay(delay);
165 }
166 }
167 var currentSuccess = MemoryEditor.ReadMemory<T>(ProcessHandler, memoryAddress!.Value, out var currentValue);
168 if (!currentValue.Equals(lastValue) || lastSuccess != currentSuccess)
169 {
170 ValueChanged?.Invoke(memoryAddress, new(lastSuccess, currentSuccess, lastValue, currentValue, customName));
171 lastValue = currentValue;
172 lastSuccess = currentSuccess;
173 }
174 await Task.Delay(delay);
175 }
176 catch { }
177 }
178 listeningFuncList.Remove(customName);
179 }
180 catch
181 {
182 goto ReStart;
183 }
184 });
87 isListening = false;
88 if (CurrentListeningTask is not null)
89 await CurrentListeningTask;
185 90 }
186 91 /// <summary>
187 /// 停止所有监听
188 /// </summary>
189 public void StopListener() => IsListening = false;
190 /// <summary>
191 /// 停止指定进程的监听
192 /// </summary>
193 /// <param name="memoryAddress">内存地址</param>
194 public void StopListener(nint memoryAddress) => listeningList[memoryAddress] = false;
195 /// <summary>
196 /// 停止指定进程的监听
197 /// </summary>
198 /// <param name="customName">自定义名称</param>
199 public void StopListener(string customName) => listeningFuncList[customName] = false;
200 /// <summary>
201 /// 内存监听器
202 /// </summary>
203 /// <param name="processName">进程名称</param>
204 public MemoryListener(string processName) => ProcessHandler = MemoryEditor.GetProcessHandle(processName, ProcessAccessFlags.All);
205 /// <summary>
206 /// 内存监听器
207 /// </summary>
208 /// <param name="processHandler">进程句柄</param>
209 public MemoryListener(nint processHandler) => ProcessHandler = processHandler;
210 /// <summary>
211 92 /// 释放资源
212 93 /// </summary>
213 94 /// <param name="disposing"></param>
214 protected virtual void Dispose(bool disposing)
95 protected void Dispose(bool disposing)
215 96 {
216 97 if (!disposedValue)
217 98 {
218 99 if (disposing)
219 100 {
220 IsListening = false;
101 isListening = false;
102 CurrentListeningTask = null;
221 103 }
222 104
223 // TODO: 释放未托管的资源(未托管的对象)并重写终结器
224 // TODO: 将大型字段设置为 null
225 105 disposedValue = true;
226 106 }
227 107 }
228
229 // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
230 // ~MemoryListener()
231 // {
232 // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
233 // Dispose(disposing: false);
234 // }
235
236 108 /// <summary>
237 /// 释放资源
109 /// 释放监听器资源
238 110 /// </summary>
239 111 public void Dispose()
240 112 {
241 // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
242 113 Dispose(disposing: true);
243 114 GC.SuppressFinalize(this);
244 115 }
116 /// <summary>
117 /// 创建内存动态地址监听器
118 /// </summary>
119 /// <param name="customName">监听器自定义标识名</param>
120 /// <param name="getAddressFunc">内存地址动态获取方法</param>
121 /// <param name="memoryAddressType">内存地址数据类型</param>
122 /// <returns></returns>
123 public static DynamicMemoryListener CreateDynamicListener(string customName, Func<nint?> getAddressFunc, Type memoryAddressType) => new DynamicMemoryListenerImpl(customName, getAddressFunc, memoryAddressType);
124 /// <summary>
125 /// 创建内存静态地址监听器
126 /// </summary>
127 /// <param name="customName">监听器自定义标识名</param>
128 /// <param name="memoryAddress">内存地址</param>
129 /// <param name="memoryAddressType">内存地址数据类型</param>
130 /// <returns></returns>
131 public static StaticMemoryListener CreateStaticListener(string customName, nint memoryAddress, Type memoryAddressType) => new StaticMemoryListenerImpl(customName, memoryAddress, memoryAddressType);
245 132 }
Modified XFEExtension.NetCore.MemoryEditor/MemoryValue.cs +1 -1
@@ -8,4 +8,4 @@
8 8 /// <param name="PreviousValue">改变前的值</param>
9 9 /// <param name="CurrentValue">当前值</param>
10 10 /// <param name="CustomName">自定义标识名</param>
11 public record struct MemoryValue(bool PreviousValueGetSuccessful, bool CurrentValueGetSuccessful, object? PreviousValue, object? CurrentValue, string? CustomName) { }
11 public record struct MemoryValue(bool PreviousValueGetSuccessful, bool CurrentValueGetSuccessful, object? PreviousValue, object? CurrentValue, string CustomName) { }
Added XFEExtension.NetCore.MemoryEditor/StaticMemoryListener.cs +54 -0
@@ -0,0 +1,54 @@
1 
2 using XFEExtension.NetCore.ImplExtension;
3
4 namespace XFEExtension.NetCore.MemoryEditor;
5
6 /// <summary>
7 /// 内存静态监听器
8 /// </summary>
9 /// <param name="customName">监听器自定义标识名</param>
10 /// <param name="memoryAddress">内存地址</param>
11 /// <param name="memoryAddressType">内存地址数据类型</param>
12 [CreateImpl]
13 public abstract class StaticMemoryListener(string customName, nint memoryAddress, Type memoryAddressType) : MemoryListener(customName, memoryAddressType)
14 {
15 private nint memoryAddress = memoryAddress;
16 /// <summary>
17 /// 内存地址
18 /// </summary>
19 public nint MemoryAddress
20 {
21 get { return memoryAddress; }
22 set { memoryAddress = value; }
23 }
24 /// <summary>
25 /// 开始监听
26 /// </summary>
27 /// <param name="processHandler">监听的进程句柄</param>
28 /// <param name="frequency">监听检测频率</param>
29 /// <returns></returns>
30 public override async Task StartListen(nint processHandler, TimeSpan frequency)
31 {
32 await base.StartListen(processHandler, frequency);
33 CurrentListeningTask = Task.Run(async () =>
34 {
35 object? lastValue = null;
36 try { lastValue = MemoryEditor.ReadMemory(processHandler, memoryAddress, memoryAddressType); } catch { }
37 while (isListening)
38 {
39 try
40 {
41 var currentValue = MemoryEditor.ReadMemory(processHandler, memoryAddress, memoryAddressType);
42 if (lastValue is null == currentValue is null || lastValue?.Equals(currentValue) == false)
43 {
44 valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, customName));
45 lastValue = currentValue;
46 }
47 await Task.Delay(frequency);
48 }
49 catch { }
50 }
51 });
52 await CurrentListeningTask;
53 }
54 }