返回提交历史
Modified
XFEExtension.NetCore.MemoryEditor/DynamicMemoryListener.cs
+1
-1
Modified
XFEExtension.NetCore.MemoryEditor/Manager/MemoryListenerManager.cs
+70
-169
Modified
XFEExtension.NetCore.MemoryEditor/MemoryListener.cs
+18
-12
Modified
XFEExtension.NetCore.MemoryEditor/StaticMemoryListener.cs
+2
-3
Added
XFEExtension.NetCore.MemoryEditor/UpdatableMemoryListener.cs
+62
-0
XFEstudio/XFEExtension.NetCore.MemoryEditor
完善内存监听器,添加可更新内存地址监听器
cb15a3d
代码差异
5 个文件
+153
-185
@@ -50,7 +50,7 @@ public abstract class DynamicMemoryListener(string customName, Func<nint?> getAd
50
50
var currentValue = MemoryEditor.ReadMemory(processHandler, memoryAddress!.Value, memoryAddressType);
51
51
if (lastValue is null == currentValue is null || lastValue?.Equals(currentValue) == false)
52
52
{
53
valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, customName));
53
valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, name));
54
54
lastValue = currentValue;
55
55
}
56
56
await Task.Delay(frequency);
@@ -10,14 +10,11 @@ namespace XFEExtension.NetCore.MemoryEditor.Manager;
10
10
public class MemoryListenerManager : IDisposable, IEnumerable
11
11
{
12
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 = [];
13
private readonly Dictionary<string, MemoryListener> listenerDictionary = [];
17
14
/// <summary>
18
15
/// 当监听值发生改变时触发
19
16
/// </summary>
20
public event XFEEventHandler<MemoryValue>? ValueChanged;
17
public event XFEEventHandler<MemoryListener, MemoryValue>? ValueChanged;
21
18
/// <summary>
22
19
/// 当前进程结束时触发
23
20
/// </summary>
@@ -40,208 +37,112 @@ public class MemoryListenerManager : IDisposable, IEnumerable
40
37
currentProcess?.Dispose();
41
38
currentProcess = value;
42
39
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)
40
currentProcess.Exited += CurrentProcess_Exited;
41
if (IsListening)
46
42
{
47
43
foreach (var listener in listenerDictionary.Values)
44
{
45
if (listener is UpdatableMemoryListener updatableMemoryListener)
46
updatableMemoryListener.UpdateAddress();
47
if (!listener.IsListening)
48
_ = listener.StartListen(ProcessHandler, listener.Frequency);
49
}
48
50
}
49
51
}
50
52
}
51
53
}
54
private async void CurrentProcess_Exited(object? sender, EventArgs e)
55
{
56
CurrentProcessExit?.Invoke(sender, e);
57
await StopListeners();
58
}
52
59
/// <summary>
53
60
/// 是否启用监听
54
61
/// </summary>
55
62
public bool IsListening { get; set; }
56
63
/// <summary>
57
/// 开始监听
64
/// 索引器
58
65
/// </summary>
59
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
60
/// <param name="memoryAddress">待监听的内存地址</param>
61
/// <param name="customName">自定义监听器标识名</param>
66
/// <param name="customName">监听器自定义标识名</param>
62
67
/// <returns></returns>
63
public async Task StartListen<T>(nint memoryAddress, string? customName = null) where T : struct
68
public MemoryListener this[string customName]
64
69
{
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
});
70
get => listenerDictionary[customName];
71
set => listenerDictionary[customName] = value;
97
72
}
98
73
/// <summary>
99
74
/// 开始监听
100
75
/// </summary>
101
76
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
102
/// <param name="memoryAddress">待监听的内存地址</param>
103
/// <param name="delay">检测频率,以毫秒为单位</param>
104
77
/// <param name="customName">自定义监听器标识名</param>
78
/// <param name="memoryAddress">待监听的内存地址</param>
79
/// <param name="frequency">检测频率,以毫秒为单位</param>
105
80
/// <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);
81
public MemoryListener AddListener<T>(string customName, nint memoryAddress, int frequency = 1) where T : struct => AddListener<T>(customName
82
, memoryAddress, TimeSpan.FromMilliseconds(frequency));
107
83
/// <summary>
108
84
/// 开始监听
109
85
/// </summary>
110
86
/// <typeparam name="T">待监听的内存的数据类型(int,float,long等)</typeparam>
111
/// <param name="memoryAddress">待监听的内存地址</param>
112
/// <param name="delay">检测频率</param>
113
87
/// <param name="customName">自定义监听器标识名</param>
88
/// <param name="memoryAddress">待监听的内存地址</param>
89
/// <param name="frequency">检测频率</param>
114
90
/// <returns></returns>
115
public async Task StartListen<T>(nint memoryAddress, TimeSpan delay, string? customName = null) where T : struct
91
public MemoryListener AddListener<T>(string customName, nint memoryAddress, TimeSpan frequency) where T : struct
116
92
{
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
});
93
150
94
}
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
95
internal StaticMemoryListener AddStaticListener(string customName, nint memoryAddress, TimeSpan frequency, Type type)
169
96
{
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
});
97
if (!IsListening)
98
IsListening = true;
99
var staticMemoryListener = MemoryListener.CreateStaticListener(customName, memoryAddress, type);
100
_ = staticMemoryListener.StartListen(ProcessHandler, frequency);
101
return staticMemoryListener;
102
}
103
internal DynamicMemoryListener AddDynamicListener(string customName, Func<nint?> memoryAddressGetFunc, TimeSpan frequency, Type type)
104
{
105
if (!IsListening)
106
IsListening = true;
107
var dynamicMemoryListener = MemoryListener.CreateDynamicListener(customName, memoryAddressGetFunc, type);
108
_ = dynamicMemoryListener.StartListen(ProcessHandler, frequency);
109
return dynamicMemoryListener;
218
110
}
219
111
/// <summary>
220
112
/// 停止所有监听
221
113
/// </summary>
222
public void StopListener()
114
public async Task StopListeners()
223
115
{
224
116
IsListening = false;
225
addressListToListen.Clear();
226
addressFuncDictionaryToListen.Clear();
117
var taskList = new List<Task>();
118
foreach (var listener in listenerDictionary.Values)
119
{
120
taskList.Add(listener.StopListen());
121
}
122
await Task.WhenAll(taskList);
227
123
}
228
124
/// <summary>
229
/// 停止指定进程的监听
125
/// 停止指定的监听器
126
/// </summary>
127
/// <param name="customName">自定义名称</param>
128
public async Task StopListener(string customName) => await listenerDictionary[customName].StopListen();
129
/// <summary>
130
/// 移除指定监听器
230
131
/// </summary>
231
/// <param name="memoryAddress">内存地址</param>
232
public void StopListener(nint memoryAddress)
132
/// <param name="customName"></param>
133
public void RemoveListener(string customName)
233
134
{
234
listeningAddressDictionary[memoryAddress] = false;
235
addressListToListen.Remove(memoryAddress);
135
listenerDictionary.Remove(customName);
136
if (listenerDictionary.Count == 0)
137
IsListening = false;
236
138
}
237
139
/// <summary>
238
/// 停止指定进程的监听
140
/// 清除所有监听器
239
141
/// </summary>
240
/// <param name="customName">自定义名称</param>
241
public void StopListener(string customName)
142
public void Clear()
242
143
{
243
listeningAddressFuncDictionary[customName] = false;
244
addressFuncDictionaryToListen.Remove(customName);
144
IsListening = false;
145
listenerDictionary.Clear();
245
146
}
246
147
/// <summary>
247
148
/// 内存监听器
@@ -288,9 +189,9 @@ public class MemoryListenerManager : IDisposable, IEnumerable
288
189
Dispose(disposing: true);
289
190
GC.SuppressFinalize(this);
290
191
}
291
292
public IEnumerator GetEnumerator()
293
{
294
throw new NotImplementedException();
295
}
192
/// <summary>
193
/// 获取枚举器
194
/// </summary>
195
/// <returns></returns>
196
public IEnumerator GetEnumerator() => listenerDictionary.GetEnumerator();
296
197
}
@@ -24,20 +24,17 @@ public abstract class MemoryListener(string customName, Type memoryAddressType)
24
24
/// <summary>
25
25
/// 监听器自定义标识名
26
26
/// </summary>
27
public string Name
28
{
29
get { return name; }
30
set { name = value; }
31
}
32
private protected Type memoryAddressType = memoryAddressType;
27
public string Name { get => name; }
28
private protected TimeSpan frequency;
29
/// <summary>
30
/// 监听检测频率
31
/// </summary>
32
public TimeSpan Frequency { get => frequency; }
33
private protected readonly Type memoryAddressType = memoryAddressType;
33
34
/// <summary>
34
35
/// 内存地址类型
35
36
/// </summary>
36
public Type MemoryAddressType
37
{
38
get { return memoryAddressType; }
39
set { memoryAddressType = value; }
40
}
37
public Type MemoryAddressType { get => memoryAddressType; }
41
38
/// <summary>
42
39
/// 是否正在监听
43
40
/// </summary>
@@ -50,7 +47,7 @@ public abstract class MemoryListener(string customName, Type memoryAddressType)
50
47
/// <summary>
51
48
/// 当前进程句柄
52
49
/// </summary>
53
public nint ProcessHandler { get => processHandler; }
50
public nint ProcessHandler { get => processHandler; set => processHandler = value; }
54
51
/// <summary>
55
52
/// 当前的监听线程
56
53
/// </summary>
@@ -67,6 +64,7 @@ public abstract class MemoryListener(string customName, Type memoryAddressType)
67
64
if (isListening)
68
65
throw new InvalidOperationException("监听已启动,无法重复启动监听");
69
66
isListening = true;
67
this.frequency = frequency;
70
68
this.processHandler = processHandler;
71
69
await Task.CompletedTask;
72
70
}
@@ -129,4 +127,12 @@ public abstract class MemoryListener(string customName, Type memoryAddressType)
129
127
/// <param name="memoryAddressType">内存地址数据类型</param>
130
128
/// <returns></returns>
131
129
public static StaticMemoryListener CreateStaticListener(string customName, nint memoryAddress, Type memoryAddressType) => new StaticMemoryListenerImpl(customName, memoryAddress, memoryAddressType);
130
/// <summary>
131
/// 创建可更新的内存地址监听器
132
/// </summary>
133
/// <param name="customName">监听器自定义标识名</param>
134
/// <param name="memoryAddressUpdateFunc">存地址动态更新方法</param>
135
/// <param name="memoryAddressType">内存地址数据类型</param>
136
/// <returns></returns>
137
public static UpdatableMemoryListener CreateUpdatableListener(string customName, Func<nint?> memoryAddressUpdateFunc, Type memoryAddressType) => new UpdatableMemoryListenerImpl(customName, memoryAddressUpdateFunc, memoryAddressType);
132
138
}
@@ -1,5 +1,4 @@
1
2
using XFEExtension.NetCore.ImplExtension;
1
using XFEExtension.NetCore.ImplExtension;
3
2
4
3
namespace XFEExtension.NetCore.MemoryEditor;
5
4
@@ -41,7 +40,7 @@ public abstract class StaticMemoryListener(string customName, nint memoryAddress
41
40
var currentValue = MemoryEditor.ReadMemory(processHandler, memoryAddress, memoryAddressType);
42
41
if (lastValue is null == currentValue is null || lastValue?.Equals(currentValue) == false)
43
42
{
44
valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, customName));
43
valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, name));
45
44
lastValue = currentValue;
46
45
}
47
46
await Task.Delay(frequency);
@@ -0,0 +1,62 @@
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="updateAddressFunc"></param>
10
/// <param name="memoryAddressType"></param>
11
[CreateImpl]
12
public abstract class UpdatableMemoryListener(string customName, Func<nint?> updateAddressFunc, Type memoryAddressType) : MemoryListener(customName, memoryAddressType)
13
{
14
private nint memoryAddress = updateAddressFunc.Invoke() ?? default;
15
/// <summary>
16
/// 内存地址
17
/// </summary>
18
public nint MemoryAddress
19
{
20
get { return memoryAddress; }
21
set { memoryAddress = value; }
22
}
23
private Func<nint?> updateAddressFunc = updateAddressFunc;
24
/// <summary>
25
/// 获取目标内存地址方法
26
/// </summary>
27
public Func<nint?> UpdateAddressFunc { get => updateAddressFunc; set => updateAddressFunc = value; }
28
/// <summary>
29
/// 开始监听
30
/// </summary>
31
/// <param name="processHandler">监听的进程句柄</param>
32
/// <param name="frequency">监听检测频率</param>
33
/// <returns></returns>
34
public override async Task StartListen(nint processHandler, TimeSpan frequency)
35
{
36
await base.StartListen(processHandler, frequency);
37
CurrentListeningTask = Task.Run(async () =>
38
{
39
object? lastValue = null;
40
try { lastValue = MemoryEditor.ReadMemory(processHandler, memoryAddress, memoryAddressType); } catch { }
41
while (isListening)
42
{
43
try
44
{
45
var currentValue = MemoryEditor.ReadMemory(processHandler, memoryAddress, memoryAddressType);
46
if (lastValue is null == currentValue is null || lastValue?.Equals(currentValue) == false)
47
{
48
valueChanged?.Invoke(this, new(lastValue is not null, currentValue is not null, lastValue, currentValue, name));
49
lastValue = currentValue;
50
}
51
await Task.Delay(frequency);
52
}
53
catch { }
54
}
55
});
56
await CurrentListeningTask;
57
}
58
/// <summary>
59
/// 更新地址值
60
/// </summary>
61
public void UpdateAddress() => memoryAddress = updateAddressFunc.Invoke() ?? memoryAddress;
62
}