原文链接

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Windows.Forms;
    4. using System.Threading.Tasks;
    5. using System.IO;
    6. using System.Reflection;
    7. using System.Text;
    8. using System.CodeDom.Compiler;
    9. using Microsoft.CSharp;
    10. namespace Excuter
    11. {
    12. static class Program
    13. {
    14. /// <summary>
    15. /// 应用程序的主入口点。
    16. /// </summary>
    17. [STAThread]
    18. static void Main(string[] args)
    19. {
    20. Application.EnableVisualStyles();
    21. Application.SetCompatibleTextRenderingDefault(false);
    22. //Application.Run(new Form1());
    23. //if (args == null || args.Length == 0) args = new string[] { @"F:\sc\桌面快捷存储\tmp\Test.cs" };
    24. if (args !=null && args.Length > 0)
    25. {
    26. // 其他参数作为执行参数
    27. string[] Arg = null;
    28. if (args.Length > 1)
    29. {
    30. Arg = new string[args.Length - 1];
    31. for (int i = 1; i < args.Length; i++)
    32. {
    33. Arg[i - 1] = args[i];
    34. }
    35. }
    36. // 第一个参数作为源码或源码文件
    37. if (File.Exists(args[0])) Excute.RunFileFirst(args[0], Arg);
    38. else Excute.RunSourceCodeFirst(args[0], Arg);
    39. }
    40. }
    41. }
    42. /// <summary>
    43. /// 动态编译执行
    44. /// </summary>
    45. public class Excute
    46. {
    47. # region 动态编译源码并执行
    48. /// <summary>
    49. /// 解析并编译执行源码文件sourceFile,第一个类的首个公用或静态方法
    50. /// </summary>
    51. public static object RunFileFirst(string sourceFile, object[] args = null)
    52. {
    53. try
    54. {
    55. string sourceCode = fileToString(sourceFile);
    56. return RunSourceCodeFirst(sourceCode, args);
    57. }
    58. catch (Exception ex)
    59. {
    60. return ex.ToString();
    61. }
    62. }
    63. /// <summary>
    64. /// 解析并编译执行sourceCode,第一个类的首个公用或静态方法
    65. /// </summary>
    66. public static object RunSourceCodeFirst(string sourceCode, object[] args = null)
    67. {
    68. try
    69. {
    70. string[] assemblies = getUsing(sourceCode).ToArray(); // 获取引用程序集
    71. string methodName = getFirstPublicMethod(sourceCode); // 获取方法名
    72. bool isStatic = isPublicStaticMethod(sourceCode, methodName); // 判断是否为静态方法
    73. return Run(sourceCode, "", methodName, args, isStatic, assemblies); // 执行
    74. }
    75. catch (Exception ex)
    76. {
    77. return ex.ToString();
    78. }
    79. }
    80. /// <summary>
    81. /// 动态编译执行
    82. /// </summary>
    83. /// <param name="sourceCode">源码</param>
    84. /// <param name="classFullName">命名空间.类</param>
    85. /// <param name="methodName">方法名</param>
    86. /// <param name="args">方法参数</param>
    87. /// <param name="assemblies">引用程序集</param>
    88. /// <param name="isStaticMethod">是否为静态方法</param>
    89. static object Run(string sourceCode, string classFullName, string methodName, object[] args = null, bool isStaticMethod = false, string[] assemblies = null)
    90. {
    91. try
    92. {
    93. // 设置编译参数 System.Xml.dll
    94. CompilerParameters param = new CompilerParameters();
    95. param.GenerateExecutable = false;
    96. param.GenerateInMemory = true;
    97. // 添加常用的默认程序集
    98. param.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
    99. param.ReferencedAssemblies.Add("mscorlib.dll");
    100. param.ReferencedAssemblies.Add("System.dll");
    101. param.ReferencedAssemblies.Add("System.Core.dll");
    102. param.ReferencedAssemblies.Add("System.Data.dll");
    103. param.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
    104. param.ReferencedAssemblies.Add("System.Drawing.dll");
    105. param.ReferencedAssemblies.Add("System.Windows.Forms.dll");
    106. param.ReferencedAssemblies.Add("System.Xml.dll");
    107. param.ReferencedAssemblies.Add("System.Xml.Linq.dll");
    108. if (assemblies != null)
    109. {
    110. foreach (string name in assemblies)
    111. {
    112. string assembly = name + ".dll";
    113. if (!param.ReferencedAssemblies.Contains(assembly))
    114. {
    115. param.ReferencedAssemblies.Add(assembly);
    116. }
    117. }
    118. }
    119. // 动态编译字符串代码
    120. CompilerResults result = new CSharpCodeProvider().CompileAssemblyFromSource(param, sourceCode);
    121. if (result.Errors.HasErrors)
    122. {
    123. // 编译出错:
    124. StringBuilder str = new StringBuilder();
    125. foreach (CompilerError err in result.Errors)
    126. {
    127. str.AppendLine(err.ErrorText);
    128. }
    129. return str.ToString();
    130. }
    131. else
    132. {
    133. // 编译通过:
    134. Assembly assembly = result.CompiledAssembly; // 获取已编译通过的程序集
    135. if (classFullName == null || classFullName.Equals("")) // 若未指定,则获取程序集第一个类路径名
    136. {
    137. classFullName = assembly.GetTypes()[0].FullName;
    138. }
    139. if (isStaticMethod)
    140. {
    141. // 调用程序集的静态方法: Type.InvokeMember
    142. Type type = assembly.GetType(classFullName, true, true);
    143. //object[] arg = new object[] { "参数1", "参数2" };
    144. object tmp = type.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, args);
    145. return tmp;
    146. }
    147. else
    148. {
    149. // 调用程序集类实例方法: method.Invoke
    150. object obj = assembly.CreateInstance(classFullName); // 创建一个类实例对象
    151. MethodInfo method = obj.GetType().GetMethod(methodName);// 获取对象的对应方法
    152. object tmp = method.Invoke(obj, args); // 调用对象的方法
    153. return tmp;
    154. }
    155. }
    156. }
    157. catch (Exception ex)
    158. {
    159. return ex.ToString();
    160. }
    161. }
    162. # endregion
    163. # region 相关功能函数
    164. /// <summary>
    165. /// 获取文件中的数据,自动判定编码格式
    166. /// </summary>
    167. private static string fileToString(String filePath)
    168. {
    169. string str = "";
    170. //获取文件内容
    171. if (File.Exists(filePath))
    172. {
    173. StreamReader file1;
    174. file1 = new StreamReader(filePath, Encoding.UTF8); // 读取文件中的数据
    175. str = file1.ReadToEnd(); // 读取文件中的全部数据
    176. file1.Close();
    177. file1.Dispose();
    178. }
    179. return str;
    180. }
    181. /// <summary>
    182. /// 获取第一个公用方法
    183. /// </summary>
    184. /// <param name="sourceCode"></param>
    185. /// <returns></returns>
    186. private static string getFirstPublicMethod(string sourceCode)
    187. {
    188. string methodName = "";
    189. String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');
    190. foreach (string iteam in lines)
    191. {
    192. string line = iteam.Trim();
    193. if (line.StartsWith("public ") && line.Contains("(") && line.Contains(")"))
    194. {
    195. methodName = line.Substring(0, line.IndexOf("("));
    196. methodName = methodName.Substring(methodName.LastIndexOf(" ") + 1);
    197. break;
    198. }
    199. }
    200. return methodName;
    201. }
    202. /// <summary>
    203. /// 判断指定的方法是否为静态方法
    204. /// </summary>
    205. /// <returns></returns>
    206. private static bool isPublicStaticMethod(string sourceCode, string methodName)
    207. {
    208. bool isStatic = false;
    209. String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');
    210. foreach (string iteam in lines)
    211. {
    212. string line = iteam.Trim();
    213. if (line.StartsWith("public ") && line.Contains(" " + methodName) && line.Contains("(") && line.Contains(")") && line.Contains("static"))
    214. {
    215. isStatic = true;
    216. }
    217. }
    218. return isStatic;
    219. }
    220. /// <summary>
    221. /// 获取应用的程序集信息
    222. /// </summary>
    223. private static List<string> getUsing(string sourceCode)
    224. {
    225. String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');
    226. List<string> usings = new List<string>();
    227. foreach (string iteam in lines)
    228. {
    229. string line = iteam.Trim();
    230. if (line.StartsWith("using ") && line.EndsWith(";"))
    231. {
    232. string usingAssembley = line.TrimEnd(';').Substring("using ".Length);
    233. CheckAddAssembly(usings, usingAssembley);
    234. }
    235. }
    236. return usings;
    237. }
    238. /// <summary>
    239. /// 检测添加较短长度的Assembly名称
    240. /// </summary>
    241. private static void CheckAddAssembly(List<string> usings, string usingAssembley)
    242. {
    243. if (usings.Contains(usingAssembley)) return;
    244. for (int i = 0; i < usings.Count; i++)
    245. {
    246. string name = usings[i];
    247. if (usingAssembley.StartsWith(name + ".")) return;
    248. else if (name.StartsWith(usingAssembley + "."))
    249. {
    250. usings[i] = usingAssembley;
    251. }
    252. }
    253. usings.Add(usingAssembley);
    254. }
    255. # endregion
    256. }
    257. }

    示例1:
    C# 动态编译执行 - 图1

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using System.Windows.Forms;
    5. namespace Demo
    6. {
    7. class Test
    8. {
    9. public static void Demo()
    10. {
    11. MessageBox.Show("动态编译执行示例!");
    12. }
    13. }
    14. }

    示例2,
    可用于动态执行的示例代码:ClearTool.cs(清除逻辑中指定的文件,拖动此文件至Excuter.exe可执行设定逻辑)

    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. namespace ClearDir2
    7. {
    8. // cmd延时执行
    9. //choice /t 2 /d y /n >nul
    10. //echo del>%~dp0test.txt
    11. //pause del %~dp0test.txt
    12. public class ClearTool
    13. {
    14. /// <summary>
    15. /// 清空目录或文件
    16. /// </summary>
    17. public static void Default()
    18. {
    19. string filePath = @"F:\sc\桌面快捷存储\tmp\dat.txt";
    20. ClearDelet(filePath);
    21. }
    22. /// <summary>
    23. /// 清空目录或文件
    24. /// </summary>
    25. public static void ClearDelet(string path)
    26. {
    27. if (File.Exists(path)) ClearDeletFile(path);
    28. if (Directory.Exists(path)) ClearDeletDirectory(path);
    29. }
    30. /// <summary>
    31. /// 先清空目录中的所有文件和子目录内容,再删除当前目录
    32. /// </summary>
    33. public static void ClearDeletDirectory(string dir)
    34. {
    35. if (Directory.Exists(dir))
    36. {
    37. // 清除目录下的所有文件
    38. foreach (String iteam in Directory.GetFiles(dir))
    39. {
    40. ClearDeletFile(iteam);
    41. }
    42. // 清除目录下的所有子目录
    43. foreach (String iteam in Directory.GetDirectories(dir))
    44. {
    45. ClearDeletDirectory(iteam);
    46. }
    47. String newName = System.IO.Directory.GetParent(dir).FullName + "\\$";
    48. while (File.Exists(newName)) newName += "$";
    49. // 清除当前目录
    50. Directory.Move(dir, newName); // 重命名当前目录,清除目录名信息
    51. Directory.Delete(newName); // 清除当前目录
    52. }
    53. }
    54. /// <summary>
    55. /// 先清空文件内容,再删除
    56. /// </summary>
    57. public static void ClearDeletFile(string file)
    58. {
    59. ClearFile(file); // 清空文件内容
    60. if (File.Exists(file))
    61. {
    62. String newName = System.IO.Directory.GetParent(file).FullName + "\\$";
    63. while (File.Exists(newName)) newName += "$";
    64. File.Move(file, newName); // 重命名文件,清除文件名称信息
    65. File.Delete(newName); // 删除文件
    66. }
    67. }
    68. /// <summary>
    69. /// 清空文件内容
    70. /// </summary>
    71. public static void ClearFile(string file)
    72. {
    73. if (File.Exists(file))
    74. {
    75. int SIZE = 1024 * 10240;
    76. byte[] array = new byte[SIZE];
    77. array.Initialize();
    78. FileStream s = new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, SIZE, FileOptions.RandomAccess);
    79. // 清空原有文件内容
    80. while (s.Position + SIZE <= s.Length - 1)
    81. {
    82. s.Write(array, 0, SIZE);
    83. }
    84. int reminds = (int)(s.Length - s.Position);
    85. if (reminds > 0) s.Write(array, 0, reminds);
    86. // 清除文件长度信息
    87. s.SetLength(0);
    88. s.Close();
    89. }
    90. }
    91. }
    92. }