动态编译执行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
{
/// <summary>
/// 应用程序的主入口点。
/// </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" };
if (args !=null && args.Length > 0)
{
// 其他参数作为执行参数
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];
}
}
// 第一个参数作为源码或源码文件
if (File.Exists(args[0])) Excute.RunFileFirst(args[0], Arg);
else Excute.RunSourceCodeFirst(args[0], Arg);
}
}
}
/// <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
{
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
}
}
示例1,
Test.cs:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace Demo
{
class Test
{
public static void Demo()
{
MessageBox.Show("动态编译执行示例!");
}
}
}
示例2,
可用于动态执行的示例代码:ClearTool.cs(清除逻辑中指定的文件,拖动此文件至Excuter.exe可执行设定逻辑)
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace ClearDir2
{
// cmd延时执行
//choice /t 2 /d y /n >nul
//echo del>%~dp0test.txt
//pause del %~dp0test.txt
public class ClearTool
{
/// <summary>
/// 清空目录或文件
/// </summary>
public static void Default()
{
string filePath = @"F:\sc\桌面快捷存储\tmp\dat.txt";
ClearDelet(filePath);
}
/// <summary>
/// 清空目录或文件
/// </summary>
public static void ClearDelet(string path)
{
if (File.Exists(path)) ClearDeletFile(path);
if (Directory.Exists(path)) ClearDeletDirectory(path);
}
/// <summary>
/// 先清空目录中的所有文件和子目录内容,再删除当前目录
/// </summary>
public static void ClearDeletDirectory(string dir)
{
if (Directory.Exists(dir))
{
// 清除目录下的所有文件
foreach (String iteam in Directory.GetFiles(dir))
{
ClearDeletFile(iteam);
}
// 清除目录下的所有子目录
foreach (String iteam in Directory.GetDirectories(dir))
{
ClearDeletDirectory(iteam);
}
String newName = System.IO.Directory.GetParent(dir).FullName + "\\$";
while (File.Exists(newName)) newName += "$";
// 清除当前目录
Directory.Move(dir, newName); // 重命名当前目录,清除目录名信息
Directory.Delete(newName); // 清除当前目录
}
}
/// <summary>
/// 先清空文件内容,再删除
/// </summary>
public static void ClearDeletFile(string file)
{
ClearFile(file); // 清空文件内容
if (File.Exists(file))
{
String newName = System.IO.Directory.GetParent(file).FullName + "\\$";
while (File.Exists(newName)) newName += "$";
File.Move(file, newName); // 重命名文件,清除文件名称信息
File.Delete(newName); // 删除文件
}
}
/// <summary>
/// 清空文件内容
/// </summary>
public static void ClearFile(string file)
{
if (File.Exists(file))
{
int SIZE = 1024 * 10240;
byte[] array = new byte[SIZE];
array.Initialize();
FileStream s = new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, SIZE, FileOptions.RandomAccess);
// 清空原有文件内容
while (s.Position + SIZE <= s.Length - 1)
{
s.Write(array, 0, SIZE);
}
int reminds = (int)(s.Length - s.Position);
if (reminds > 0) s.Write(array, 0, reminds);
// 清除文件长度信息
s.SetLength(0);
s.Close();
}
}
}
}