-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathRemoteUtil.cs
299 lines (283 loc) · 12.7 KB
/
RemoteUtil.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.CodeDom.Compiler;
using System.IO;
using Microsoft.CSharp;
using System.Collections;
using System.Collections.Concurrent;
using System.IO;
namespace DynamicUtil
{
/// <summary>影子程序域的代理对象,改类不处理调用过程的异常
/// </summary>
public class RemoteUtil : MarshalByRefObject
{
/// <summary>跨域调用使生命周期无限
/// </summary>
/// <returns>null</returns>
public override object InitializeLifetimeService()
{
return null; // makes the object live indefinitely
}
/// <summary>锁
/// </summary>
private static ConcurrentDictionary<string, object> ht_locks = new ConcurrentDictionary<string, object>();
/// <summary>指定路径下的文件最新标识
/// </summary>
private static ConcurrentDictionary<string, object> ht_last_flags = new ConcurrentDictionary<string, object>();
/// <summary>指定路径下加载的最新程序集
/// </summary>
private static ConcurrentDictionary<string, object> ht_last_assem = new ConcurrentDictionary<string, object>();
private static string GeneLastFlag(string filePath)
{
return "[" + File.GetLastWriteTime(filePath).ToString("yyyyMMddHHmmssfff") + "]" + filePath;
}
private static object GetLock(string filePath)
{
object objtmp;
if (!ht_locks.TryGetValue(filePath, out objtmp))
{
lock (typeof(MainlUtil))
{
if (!ht_locks.TryGetValue(filePath, out objtmp))
{
ht_locks.TryAdd(filePath, new object());
}
return ht_locks[filePath];
}
}
else
{
return objtmp;
}
}
/// <summary>动态调用指定路径的程序集的指定类指定方法
/// </summary>
/// <param name="dllPath">程序集路径</param>
/// <param name="fullClassName">类全名</param>
/// <param name="methodName">方法全名</param>
/// <param name="paraTypes">方法参数类型(没有参数用"new Type[]{}"代替)</param>
/// <param name="args">方法参数实例(没有参数用"new object[]{}"代替)</param>
/// <returns>返回的HashTable中有两个元素一个是key为"Success"的bool,为true,代表调用成功,为false代表调用失败,另一个是key为"Data"的object,代表调用方法返回的结果或程序异常的信息</returns>
public Hashtable InvokeDll(string dllFullName, string classFullName, string methodName, Type[] paraTypes, object[] args)
{
Assembly assem = Assembly.Load(dllFullName);
return InvokeDll(assem, classFullName, methodName, paraTypes, args);
}
public Hashtable InvokeDll(string typename, string methodName, Type[] paraTypes, object[] args)
{
Type t = Type.GetType(typename);
return InvokeDll(t, methodName, paraTypes, args);
}
/// <summary>动态调用指定程序集的指定类指定方法
/// </summary>
/// <param name="assem">指定的程序集对象</param>
/// <param name="fullClassName">类全名</param>
/// <param name="methodName">方法全名</param>
/// <param name="paraTypes">方法参数类型(没有参数用"new Type[]{}"代替)</param>
/// <param name="args">方法参数实例(没有参数用"new object[]{}"代替)</param>
/// <returns>返回的HashTable中有两个元素一个是key为"Success"的bool,为true,代表调用成功,为false代表调用失败,另一个是key为"Data"的object,代表调用方法返回的结果或程序异常的信息</returns>
public Hashtable InvokeDll(Assembly assem, string classFullName, string methodName, Type[] paraTypes, object[] args)
{
Hashtable ht = new Hashtable();
Type t = assem.GetType(classFullName);
if (t == null)
{
ht.Add("Success", false);
ht.Add("Data", "[类:" + classFullName + "]没找到");
return ht;
}
return InvokeDll(t, methodName, paraTypes, args);
}
/// <summary>动态调用指定类类型的指定方法
/// </summary>
/// <param name="t">指定的类类型</param>
/// <param name="methodName">方法全名</param>
/// <param name="paraTypes">方法参数类型(没有参数用"new Type[]{}"代替)</param>
/// <param name="args">方法参数实例(没有参数用"new object[]{}"代替)</param>
/// <returns>返回的HashTable中有两个元素一个是key为"Success"的bool,为true,代表调用成功,为false代表调用失败,另一个是key为"Data"的object,代表调用方法返回的结果或程序异常的信息</returns>
public Hashtable InvokeDll(Type t, string methodName, Type[] paraTypes, object[] args)
{
Hashtable ht = new Hashtable();
if (t == null)
{
ht.Add("Success", false);
ht.Add("Data", "[类:null]没找到");
return ht;
}
MethodInfo minfo = t.GetMethod(methodName, paraTypes);
if (minfo == null)
{
ht.Add("Success", false);
ht.Add("Data", "[类:" + t.FullName + "][方法:" + methodName + "]没找到");
return ht;
}
object obj = Activator.CreateInstance(t);
if (obj == null)
{
ht.Add("Success", false);
ht.Add("Data", "[类:" + t.FullName + "]创建实例失败");
return ht;
}
object objres = minfo.Invoke(obj, args);
ht.Add("Success", true);
ht.Add("Data", objres);
return ht;
}
/// <summary>动态调用指定类类型的指定方法
/// </summary>
/// <param name="exePath">exe程序的路径</param>
/// <param name="paras">参数为字符串数组</param>
/// <returns>返回的HashTable中有两个元素一个是key为"Success"的bool,为true,代表调用成功,为false代表调用失败,另一个是key为"Data"的object,代表程序异常的信息</returns>
public Hashtable InvokeExe(string exePath, string[] paras)
{
Assembly assem = Assembly.Load(exePath);
MethodInfo minfo = assem.EntryPoint;
if (minfo.GetParameters().Length == 1)
{
//入口函数有一个参数
if (paras == null)
{
//提供的没有参数就默认搞个空的字符串数组作为参数传进去
minfo.Invoke(null, new object[] { new string[] { } });
}
else
{
//提供的有参数就直接传进去
minfo.Invoke(null, new object[] { paras });
}
}
else
{
//入口函数没有参数
minfo.Invoke(null, new object[] { });
}
Hashtable ht = new Hashtable();
ht.Add("Success", true);
return ht;
}
/// <summary>动态编译一个代码文件并执行
/// </summary>
/// <param name="srcCodePath">源代码路径</param>
/// <param name="classFullName">调用的类全名</param>
/// <param name="methodName">调用的方法名</param>
/// <param name="paraTypes">方法参数类型(没有参数用"new Type[]{}"代替)</param>
/// <param name="args">方法参数实例(没有参数用"new object[]{}"代替)</param>
/// <returns>返回的HashTable中有两个元素一个是key为"Success"的bool,为true,代表调用成功,为false代表调用失败,另一个是key为"Data"的object,代表调用方法返回的结果或程序异常的信息</returns>
public Hashtable InvokeSrc(string srcCodePath, string classFullName,
string methodName,
Type[] paraTypes,
object[] args)
{
string value = GeneLastFlag(srcCodePath);
object lockobj = GetLock(srcCodePath);
lock (lockobj)
{
object tmp;
if (ht_last_flags.TryGetValue(srcCodePath, out tmp))
{
if (tmp.ToString() != value)
{
ht_last_assem[srcCodePath] = Compile(srcCodePath);
ht_last_flags[srcCodePath] = value;
}
}
else
{
ht_last_assem.TryAdd(srcCodePath, Compile(srcCodePath));
ht_last_flags.TryAdd(srcCodePath, value);
}
}
return InvokeDll(ht_last_assem[srcCodePath] as Assembly, classFullName, methodName, paraTypes, args);
}
/// <summary>编译源代码,返回编译好的程序集
/// </summary>
/// <param name="srcCodePath">源代码路径</param>
/// <returns></returns>
private Assembly Compile(string srcCodePath)
{
System.CodeDom.Compiler.CompilerParameters parameters = new System.CodeDom.Compiler.CompilerParameters();
string srcCode = "";
ParseSrc(srcCodePath, ref srcCode, parameters);
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
using (var provider = new CSharpCodeProvider())
{
CompilerResults results = provider.CompileAssemblyFromSource(parameters, srcCode);
CompilerErrorCollection errorcollection = results.Errors;
string errorMsg = "";
foreach (CompilerError error in errorcollection)
{
if (error.IsWarning == true)
{
errorMsg = "Line: " + error.Line.ToString() + " Warning Number: " + error.ErrorNumber + " Warning Message: " + error.ErrorText + "\r\n";
}
else if (error.IsWarning == false)
{
errorMsg = "Line: " + error.Line.ToString() + " Error Number: " + error.ErrorNumber + " Error Message: " + error.ErrorText + "\r\n";
}
}
if (errorcollection.Count > 0)
{
throw new Exception("[编译出错]" + errorMsg);
}
return results.CompiledAssembly;
}
}
/// <summary>解析源代码,主要解析引用
/// </summary>
/// <param name="srcCodePath"></param>
/// <param name="srcCode"></param>
/// <param name="parameters"></param>
private void ParseSrc(string srcCodePath, ref string srcCode, CompilerParameters parameters)
{
string[] lines = File.ReadAllLines(srcCodePath);
srcCode = "";
bool b = true;//为true表示还在解析程序集的引用
foreach (var item in lines)
{
string tmp = item.Trim(' ');
if (tmp.StartsWith("//#import"))
{
if (b)
{
tmp = tmp.Substring(9).Trim(' ');
tmp = ParseFilePath(tmp);
if (!string.IsNullOrWhiteSpace(tmp))
{
parameters.ReferencedAssemblies.Add(tmp);
}
}
}
else
{
b = false;
srcCode += "\r\n" + tmp;
}
}
}
public string ParseFilePath(string path)
{
//为空直接返回
if (string.IsNullOrWhiteSpace(path)) { return path; }
//包含":"表示绝对路径,直接返回
if (path.Contains(":")) { return path; }
path = path.Replace("/", "\\");
//不以~或\\开头,就不用引用程序集的绝对路径
if (!(path.StartsWith("~") || path.StartsWith("\\"))) { return path; }
if (path.StartsWith("~"))
{
path = path.TrimStart('~');
}
if (path.StartsWith("\\"))
{
path = path.TrimStart('\\');
}
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
}
}
}