返回提交历史
Added
XFEExtension.NetCore.MemoryEditor/DynamicMemoryListener.cs
+63
-0
Renamed
XFEExtension.NetCore.MemoryEditor/Manager/DynamicMemoryManager.cs
+2
-7
Modified
XFEExtension.NetCore.MemoryEditor/Manager/MemoryItem.cs
+6
-2
Added
XFEExtension.NetCore.MemoryEditor/Manager/MemoryListenerManager.cs
+296
-0
Modified
XFEExtension.NetCore.MemoryEditor/Manager/MemoryManager.cs
+2
-2
Modified
XFEExtension.NetCore.MemoryEditor/Manager/StaticMemoryItem.cs
+8
-1
Renamed
XFEExtension.NetCore.MemoryEditor/Manager/StaticMemoryManager.cs
+2
-7
Modified
XFEExtension.NetCore.MemoryEditor/MemoryEditor.cs
+29
-18
Modified
XFEExtension.NetCore.MemoryEditor/MemoryListener.cs
+75
-188
Modified
XFEExtension.NetCore.MemoryEditor/MemoryValue.cs
+1
-1
Added
XFEExtension.NetCore.MemoryEditor/StaticMemoryListener.cs
+54
-0
XFEstudio/XFEExtension.NetCore.MemoryEditor
将监听器分类为动态和静态
f31902e
代码差异
11 个文件
+538
-226
@@ -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
}
@@ -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>
@@ -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>
@@ -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
}
@@ -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
{
@@ -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
}
@@ -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
{
@@ -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;
@@ -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
}
@@ -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) { }
@@ -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
}