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)
{
// 判断参数中是否含有DEBUG
List<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.dll
CompilerParameters 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.InvokeMember
Type 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.Invoke
object 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",vbhide
StringBuilder 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