Excuter.exe 动态编译执行器,可执行任意逻辑,实现源码与工具的分离。
源码:
using System;using System.Collections.Generic;using System.Windows.Forms;using System.Threading.Tasks;using System.IO;using System.Reflection;using System.Text;using System.CodeDom.Compiler;using Microsoft.CSharp;namespace Excuter{static class Program{public static bool isDebug = false;public static int delayMillionSecond = 0;public static string sourceCode = "";public static object[] sourceArgs = null;public static bool autoDelet = false;/// <summary>/// 应用程序的主入口点。可直接传入源码、或源码文件路径。DEBUG标识是否输出运行信息。DELAY标识延时毫秒时间值。AUTODELET是否自删除。/// </summary>[STAThread]static void Main(string[] args){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);//Application.Run(new Form1());//if (args == null || args.Length == 0) args = new string[] { @"F:\sc\桌面快捷存储\tmp\Test.cs" };//string source = @"D:\sci\Visual Studio 2008\Projects\ClearDir\ClearDir\Resources\ClearTool.txt";//string source = @"D:\sci\Visual Studio 2008\Projects\ClearDir\ClearDir\bin\Debug\Code.txt";//if (args == null || args.Length == 0) args = new string[] { source, @"F:\sc\桌面快捷存储\tmp\新建文本文档.txt" };if (args !=null && args.Length > 0){// 判断参数中是否含有DEBUGList<string> arglist = new List<string>();foreach (string arg in args){if (arg.Equals("DEBUG")) isDebug = true;else if (arg.Equals("AUTODELET")) autoDelet = true;else if (arg.StartsWith("DELAY")) delayMillionSecond = int.Parse(arg.Substring("DELAY".Length));else arglist.Add(arg);}args = arglist.ToArray();// 其他参数作为执行参数string[] Arg = null;if (args.Length > 1){Arg = new string[args.Length - 1];for (int i = 1; i < args.Length; i++){Arg[i - 1] = args[i];}}sourceCode = args[0];sourceArgs = new object[] { Arg };ExcuteProcess(); // 执行逻辑Application.Run(); // 在当前线程上运行应用程序消息循环}else if (autoDelet) AutoDelet.deletItself();}/// <summary>/// 根据param中的参数控制截屏/// </summary>public static void ExcuteProcess(){if (delayMillionSecond > 0){Timer timer = new Timer();timer.Interval = delayMillionSecond;timer.Tick += Timer_Tick;delayMillionSecond = 0;timer.Enabled = true;}else{// 第一个参数作为源码或源码文件object result = "";if (File.Exists(sourceCode)) result = Excute.RunFileFirst(sourceCode, sourceArgs);else result = Excute.RunSourceCodeFirst(sourceCode, sourceArgs);if (isDebug && result != null) MessageBox.Show(sourceCode + "\r\n" + result.ToString());if (autoDelet) AutoDelet.deletItself();exit();}}/// <summary>/// 延时截屏处理逻辑/// </summary>private static void Timer_Tick(object sender, EventArgs e){((Timer)sender).Stop(); // 停止计时ExcuteProcess(); // 执行逻辑}/// <summary>/// 调用系统退出/// </summary>public static void exit(){//Application.Exit();//Application.ExitThread();System.Environment.Exit(0);}}/// <summary>/// 动态编译执行/// </summary>public class Excute{# region 动态编译源码并执行/// <summary>/// 解析并编译执行源码文件sourceFile,第一个类的首个公用或静态方法/// </summary>public static object RunFileFirst(string sourceFile, object[] args = null){try{string sourceCode = fileToString(sourceFile); // 读取文件内容return RunSourceCodeFirst(sourceCode, args); // 执行}catch (Exception ex){return ex.ToString();}}/// <summary>/// 解析并编译执行sourceCode,第一个类的首个公用或静态方法/// </summary>public static object RunSourceCodeFirst(string sourceCode, object[] args = null){try{sourceCode = Encoder.Decode(sourceCode); // 解析源码string[] assemblies = getUsing(sourceCode).ToArray(); // 获取引用程序集string methodName = getFirstPublicMethod(sourceCode); // 获取方法名bool isStatic = isPublicStaticMethod(sourceCode, methodName); // 判断是否为静态方法return Run(sourceCode, "", methodName, args, isStatic, assemblies); // 执行}catch (Exception ex){return ex.ToString();}}/// <summary>/// 动态编译执行/// </summary>/// <param name="sourceCode">源码</param>/// <param name="classFullName">命名空间.类</param>/// <param name="methodName">方法名</param>/// <param name="args">方法参数</param>/// <param name="assemblies">引用程序集</param>/// <param name="isStaticMethod">是否为静态方法</param>static object Run(string sourceCode, string classFullName, string methodName, object[] args = null, bool isStaticMethod = false, string[] assemblies = null){try{// 设置编译参数 System.Xml.dllCompilerParameters param = new CompilerParameters();param.GenerateExecutable = false;param.GenerateInMemory = true;// 添加常用的默认程序集param.ReferencedAssemblies.Add("Microsoft.CSharp.dll");param.ReferencedAssemblies.Add("mscorlib.dll");param.ReferencedAssemblies.Add("System.dll");param.ReferencedAssemblies.Add("System.Core.dll");param.ReferencedAssemblies.Add("System.Data.dll");param.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");param.ReferencedAssemblies.Add("System.Drawing.dll");param.ReferencedAssemblies.Add("System.Windows.Forms.dll");param.ReferencedAssemblies.Add("System.Xml.dll");param.ReferencedAssemblies.Add("System.Xml.Linq.dll");if (assemblies != null){foreach (string name in assemblies){string assembly = name + ".dll";if (!param.ReferencedAssemblies.Contains(assembly)){param.ReferencedAssemblies.Add(assembly);}}}// 动态编译字符串代码CompilerResults result = new CSharpCodeProvider().CompileAssemblyFromSource(param, sourceCode);if (result.Errors.HasErrors){// 编译出错:StringBuilder str = new StringBuilder();foreach (CompilerError err in result.Errors){str.AppendLine(err.ErrorText);}return str.ToString();}else{// 编译通过:Assembly assembly = result.CompiledAssembly; // 获取已编译通过的程序集if (classFullName == null || classFullName.Equals("")) // 若未指定,则获取程序集第一个类路径名{classFullName = assembly.GetTypes()[0].FullName;}if (isStaticMethod){// 调用程序集的静态方法: Type.InvokeMemberType type = assembly.GetType(classFullName, true, true);//object[] arg = new object[] { "参数1", "参数2" };object tmp = type.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, args);return tmp;}else{// 调用程序集类实例方法: method.Invokeobject obj = assembly.CreateInstance(classFullName); // 创建一个类实例对象MethodInfo method = obj.GetType().GetMethod(methodName);// 获取对象的对应方法object tmp = method.Invoke(obj, args); // 调用对象的方法return tmp;}}}catch (Exception ex){return ex.ToString();}}# endregion# region 相关功能函数/// <summary>/// 获取文件中的数据,自动判定编码格式/// </summary>private static string fileToString(String filePath){string str = "";//获取文件内容if (File.Exists(filePath)){StreamReader file1;file1 = new StreamReader(filePath, Encoding.UTF8); // 读取文件中的数据str = file1.ReadToEnd(); // 读取文件中的全部数据file1.Close();file1.Dispose();}return str;}/// <summary>/// 获取第一个公用方法/// </summary>/// <param name="sourceCode"></param>/// <returns></returns>private static string getFirstPublicMethod(string sourceCode){string methodName = "";String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');foreach (string iteam in lines){string line = iteam.Trim();if (line.StartsWith("public ") && line.Contains("(") && line.Contains(")")){methodName = line.Substring(0, line.IndexOf("("));methodName = methodName.Substring(methodName.LastIndexOf(" ") + 1);break;}}return methodName;}/// <summary>/// 判断指定的方法是否为静态方法/// </summary>/// <returns></returns>private static bool isPublicStaticMethod(string sourceCode, string methodName){bool isStatic = false;String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');foreach (string iteam in lines){string line = iteam.Trim();if (line.StartsWith("public ") && line.Contains(" " + methodName) && line.Contains("(") && line.Contains(")") && line.Contains("static")){isStatic = true;}}return isStatic;}/// <summary>/// 获取应用的程序集信息/// </summary>private static List<string> getUsing(string sourceCode){String[] lines = sourceCode.Replace("\r\n", "\n").Split('\n');List<string> usings = new List<string>();foreach (string iteam in lines){string line = iteam.Trim();if (line.StartsWith("using ") && line.EndsWith(";")){string usingAssembley = line.TrimEnd(';').Substring("using ".Length);CheckAddAssembly(usings, usingAssembley);}}return usings;}/// <summary>/// 检测添加较短长度的Assembly名称/// </summary>private static void CheckAddAssembly(List<string> usings, string usingAssembley){if (usings.Contains(usingAssembley)) return;for (int i = 0; i < usings.Count; i++){string name = usings[i];if (usingAssembley.StartsWith(name + ".")) return;else if (name.StartsWith(usingAssembley + ".")){usings[i] = usingAssembley;}}usings.Add(usingAssembley);}# endregion}public class Encoder{public static void example(){String data = "test encode";string encode = Encode(data);string decode = Decode(encode);bool b = data.Equals(decode);bool b2 = b;}/// <summary>/// 转码data为全字母串,并添加前缀/// </summary>public static string Encode(string data){string str = data;if (!data.StartsWith("ALPHABETCODE@")){str = "ALPHABETCODE@" + EncodeAlphabet(data);}return str;}/// <summary>/// 解析字母串为原有串/// </summary>public static string Decode(string data){string str = data;if (data.StartsWith("ALPHABETCODE@")){str = DecodeAlphabet(data.Substring("ALPHABETCODE@".Length));}return str;}# region 字符串字母编码逻辑/// <summary>/// 转化为字母字符串/// </summary>public static string EncodeAlphabet(string data){byte[] B = Encoding.UTF8.GetBytes(data);return ToStr(B);}/// <summary>/// 每个字节转化为两个字母/// </summary>private static string ToStr(byte[] B){StringBuilder Str = new StringBuilder();foreach (byte b in B){Str.Append(ToStr(b));}return Str.ToString();}private static string ToStr(byte b){return "" + ToChar(b / 16) + ToChar(b % 16);}private static char ToChar(int n){return (char)('a' + n);}/// <summary>/// 解析字母字符串/// </summary>public static string DecodeAlphabet(string data){byte[] B = new byte[data.Length / 2];char[] C = data.ToCharArray();for (int i = 0; i < C.Length; i += 2){byte b = ToByte(C[i], C[i + 1]);B[i / 2] = b;}return Encoding.UTF8.GetString(B);}/// <summary>/// 每两个字母还原为一个字节/// </summary>private static byte ToByte(char a1, char a2){return (byte)((a1 - 'a') * 16 + (a2 - 'a'));}# endregion}public class AutoDelet{/// <summary>/// 应用自删除/// </summary>public static void deletItself(){try{string curExe = System.Windows.Forms.Application.ExecutablePath;string tmpName = AppDomain.CurrentDomain.BaseDirectory + "$";string name1 = "$";while (File.Exists(tmpName)){tmpName = tmpName + "$";name1 = name1 + "$";}File.Move(curExe, tmpName); // 重命名当前文件string vbsName = AppDomain.CurrentDomain.BaseDirectory + "$";string name2 = "$";while (File.Exists(vbsName + ".vbs")){vbsName = vbsName + "$";name2 = name2 + "$";}//Set ws = CreateObject("Wscript.Shell")//WScript.sleep 5000//ws.run "cmd /c ?> $",vbhide//ws.run "cmd /c del $",vbhide//ws.run "cmd /c ?> $.vbs",vbhide//ws.run "cmd /c del $.vbs",vbhideStringBuilder Str = new StringBuilder();Str.AppendLine("Set ws = CreateObject(\"Wscript.Shell\")");Str.AppendLine("WScript.sleep 4000");Str.AppendLine("ws.run \"cmd /c ?> " + name1 + "\",vbhide");Str.AppendLine("ws.run \"cmd /c del " + name1 + "\",vbhide");Str.AppendLine("ws.run \"cmd /c ?> " + name2 + ".vbs\",vbhide");Str.AppendLine("ws.run \"cmd /c del " + name2 + ".vbs\",vbhide");string data = Str.ToString();SaveFile(data, vbsName + ".vbs");System.Diagnostics.Process.Start(vbsName + ".vbs");System.Environment.Exit(0); //退出}catch (Exception) { }}/// <summary>/// 保存数据data到文件处理过程,返回值为保存的文件名/// </summary>private static String SaveFile(String data, String filePath){System.IO.StreamWriter file1 = new System.IO.StreamWriter(filePath, false, Encoding.Default); //文件已覆盖方式添加内容file1.Write(data); //保存数据到文件file1.Close(); //关闭文件file1.Dispose(); //释放对象return filePath;}}}
————————————————
版权声明:本文为CSDN博主「scimence」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/scimence/article/details/76981225
