2023-08-12 01:43:24 +08:00
|
|
|
using System;
|
2024-01-27 04:09:57 +08:00
|
|
|
using System.CodeDom.Compiler;
|
2023-08-12 01:43:24 +08:00
|
|
|
using System.Collections.Concurrent;
|
2024-01-27 04:09:57 +08:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
2023-08-12 01:43:24 +08:00
|
|
|
using System.Reflection;
|
2024-01-27 04:09:57 +08:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using BITKit.Mod;
|
|
|
|
using Microsoft.CSharp;
|
|
|
|
|
|
|
|
#if UNITY_64
|
|
|
|
using static BITKit.Mod.MonoBleedingEdgeService;
|
|
|
|
#endif
|
2023-08-12 01:43:24 +08:00
|
|
|
|
|
|
|
namespace BITKit
|
|
|
|
{
|
|
|
|
public class BITSharp
|
|
|
|
{
|
2024-01-27 04:09:57 +08:00
|
|
|
public static readonly List<string> ReferencedAssemblies = new();
|
2023-08-12 01:43:24 +08:00
|
|
|
private static readonly ConcurrentDictionary<string, Type> Dictionary = new();
|
2024-01-27 04:09:57 +08:00
|
|
|
private static Assembly[] assemblies;
|
|
|
|
|
|
|
|
public static bool TryGetTypeFromFullName(string fullClassName, out Type type)
|
2023-08-12 01:43:24 +08:00
|
|
|
{
|
|
|
|
type = GetTypeFromFullName(fullClassName);
|
|
|
|
return type is not null ? true : false;
|
|
|
|
}
|
2024-01-27 04:09:57 +08:00
|
|
|
|
2023-08-12 01:43:24 +08:00
|
|
|
public static Type GetTypeFromFullName(string fullClassName)
|
|
|
|
{
|
|
|
|
return Dictionary.GetOrAdd(fullClassName, SearchType);
|
|
|
|
}
|
2024-01-27 04:09:57 +08:00
|
|
|
|
|
|
|
private static Type SearchType(string fullName)
|
2023-08-12 01:43:24 +08:00
|
|
|
{
|
2024-01-27 04:09:57 +08:00
|
|
|
assemblies = assemblies ?? AppDomain.CurrentDomain.GetAssemblies();
|
2023-08-12 01:43:24 +08:00
|
|
|
foreach (var assembly in assemblies)
|
|
|
|
{
|
2024-01-27 04:09:57 +08:00
|
|
|
var type = assembly.GetType(fullName, false);
|
2023-08-12 01:43:24 +08:00
|
|
|
if (type is not null)
|
|
|
|
{
|
2024-01-27 04:09:57 +08:00
|
|
|
return type;
|
2023-08-12 01:43:24 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2024-01-27 04:09:57 +08:00
|
|
|
|
2023-08-12 01:43:24 +08:00
|
|
|
return null;
|
|
|
|
}
|
2024-01-27 04:09:57 +08:00
|
|
|
#if UNITY_64
|
|
|
|
|
|
|
|
|
|
|
|
public static Assembly Compile(params string[] codes)
|
|
|
|
{
|
|
|
|
var outputPath = PathHelper.GetTempFilePath();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (MonoBleedingEdgeService.Installed is false)
|
|
|
|
{
|
|
|
|
throw new FileNotFoundException($"未从当前路径找到mcs:\n{MCSPath}");
|
|
|
|
}
|
|
|
|
|
|
|
|
var argumentBuilder = new StringBuilder();
|
|
|
|
var dllPath = Assembly.GetExecutingAssembly().Location;
|
|
|
|
|
|
|
|
var tempList = new List<string> { outputPath };
|
|
|
|
|
|
|
|
foreach (var code in codes)
|
|
|
|
{
|
|
|
|
var temp = PathHelper.GetTempFilePath();
|
|
|
|
|
|
|
|
File.WriteAllText(temp,code);
|
|
|
|
|
|
|
|
argumentBuilder.Append(" ");
|
|
|
|
argumentBuilder.Append(temp);
|
|
|
|
|
|
|
|
tempList.Add(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
argumentBuilder.Append(" ");
|
|
|
|
argumentBuilder.Append("-target:library");
|
|
|
|
|
|
|
|
// foreach (var fileInfo in new FileInfo(Assembly.GetExecutingAssembly()!.Location!).Directory!.GetFiles())
|
|
|
|
// {
|
|
|
|
// if(fileInfo.Extension is not ".dll")continue;
|
|
|
|
//
|
|
|
|
// argumentBuilder.Append(" ");
|
|
|
|
// argumentBuilder.Append("-r:");
|
|
|
|
// argumentBuilder.Append(fileInfo.FullName);
|
|
|
|
// }
|
|
|
|
|
|
|
|
foreach (var x in ReferencedAssemblies)
|
|
|
|
{
|
|
|
|
argumentBuilder.Append(" ");
|
|
|
|
argumentBuilder.Append("-r:");
|
|
|
|
argumentBuilder.Append(Path.Combine(dllPath, x));
|
|
|
|
}
|
|
|
|
|
|
|
|
argumentBuilder.Append(" ");
|
|
|
|
argumentBuilder.Append($"-out:{outputPath}");
|
|
|
|
|
|
|
|
BIT4Log.Log<BITSharp>("已创建编译参数:");
|
|
|
|
BIT4Log.Log(argumentBuilder.ToString());
|
|
|
|
|
|
|
|
var StartInfo = new ProcessStartInfo
|
|
|
|
{
|
|
|
|
FileName = MCSPath,
|
|
|
|
Arguments = argumentBuilder.ToString(),
|
|
|
|
UseShellExecute = true,
|
|
|
|
CreateNoWindow = false,
|
|
|
|
};
|
|
|
|
var process = new Process()
|
|
|
|
{
|
|
|
|
StartInfo = StartInfo,
|
|
|
|
};
|
|
|
|
process.OutputDataReceived += (sender, args) =>
|
|
|
|
{
|
|
|
|
BIT4Log.Log<BITSharp>(args.Data);
|
|
|
|
};
|
|
|
|
process.ErrorDataReceived += (sender, args) =>
|
|
|
|
{
|
|
|
|
BIT4Log.Warning<BITSharp>(args.Data);
|
|
|
|
};
|
|
|
|
|
|
|
|
//var exited=false;
|
|
|
|
process.Start();
|
|
|
|
BIT4Log.Log<BITSharp>("已启动");
|
|
|
|
process.WaitForExit();
|
|
|
|
// process.Exited += (sender, args) =>
|
|
|
|
// {
|
|
|
|
// exited = true;
|
|
|
|
// BIT4Log.Log<BITSharp>("已退出");
|
|
|
|
// };
|
|
|
|
// BIT4Log.Log<BITSharp>("完成");
|
|
|
|
//
|
|
|
|
// while (exited is false && process.HasExited is false)
|
|
|
|
// {
|
|
|
|
// Thread.Sleep(100);
|
|
|
|
// }
|
|
|
|
|
|
|
|
var bytes = File.ReadAllBytes(outputPath);
|
|
|
|
|
|
|
|
foreach (var x in tempList)
|
|
|
|
{
|
|
|
|
File.Delete(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Assembly.Load(bytes);
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
throw new Exception($"编译失败:{e}");
|
|
|
|
}
|
|
|
|
// if (BITAppForUnity.IsEditor)
|
|
|
|
// {
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
|
|
|
|
var codeProvider = new CSharpCodeProvider();
|
|
|
|
var parameters = new CompilerParameters
|
|
|
|
{
|
|
|
|
GenerateInMemory = true,
|
|
|
|
CompilerOptions = "/unsafe",
|
|
|
|
OutputAssembly = outputPath,
|
|
|
|
};
|
|
|
|
parameters.ReferencedAssemblies.Add("System.dll");
|
|
|
|
foreach (var x in ReferencedAssemblies)
|
|
|
|
{
|
|
|
|
parameters.ReferencedAssemblies.Add(x);
|
|
|
|
BIT4Log.Log<BITSharp>($"添加引用:");
|
|
|
|
BIT4Log.Log<BITSharp>(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
BIT4Log.Log<BITSharp>($"程序集输出路径:{outputPath}");
|
|
|
|
|
|
|
|
var results = codeProvider.CompileAssemblyFromSource(parameters, codes);
|
|
|
|
|
|
|
|
if (results.Errors.Count <= 0)
|
|
|
|
{
|
|
|
|
BIT4Log.Log<BITSharp>($"编译成功:{results.CompiledAssembly.FullName}");
|
|
|
|
|
|
|
|
codeProvider.Dispose();
|
|
|
|
return results.CompiledAssembly;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (CompilerError error in results.Errors)
|
|
|
|
{
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
sb.AppendLine(error.FileName);
|
|
|
|
sb.AppendLine($"Error ({error.ErrorNumber}): {error.ErrorText}");
|
|
|
|
sb.AppendLine($"Line: {error.Line}, Column: {error.Column}");
|
|
|
|
sb.AppendLine($"Is Warning: {error.IsWarning}");
|
|
|
|
BIT4Log.LogException(new Exception(sb.ToString()));
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Exception("编译失败");
|
|
|
|
}
|
|
|
|
#endif
|
2023-08-12 01:43:24 +08:00
|
|
|
}
|
|
|
|
}
|