using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;using System.IO;using System.Windows.Forms;using Microsoft.CodeAnalysis;using Microsoft.CodeAnalysis.CSharp;using Microsoft.CodeAnalysis.Emit;namespace AppBasicIDE{public class ScriptEngine{private Dictionary<string, Assembly> _compiledScripts = new Dictionary<string, Assembly>();private ControlManager _controlManager;public ScriptEngine(ControlManager controlManager = null){_controlManager = controlManager;}public void SetControlManager(ControlManager controlManager){_controlManager = controlManager;}public bool CompileScript(string scriptId, string code, out string error){error = null;try{// 生成控件访问代码var controlAccessCode = GenerateControlAccessCode();// 包装代码到一个类中,包含控件访问功能var wrappedCode = $@"using System;using System.Windows.Forms;using System.Drawing;public class ScriptClass{{private System.Collections.Generic.Dictionary<string, Control> _controls;public void SetControls(System.Collections.Generic.Dictionary<string, Control> controls){{_controls = controls;}}{controlAccessCode}public void Execute(Control sender, EventArgs e){{{code}}}}}";var syntaxTree = CSharpSyntaxTree.ParseText(wrappedCode);// 获取所有必要的引用程序集var references = GetMetadataReferences();var compilation = CSharpCompilation.Create(assemblyName: $"Script_{scriptId}_{Guid.NewGuid():N}",syntaxTrees: new[] { syntaxTree },references: references,options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));using (var ms = new MemoryStream()){EmitResult result = compilation.Emit(ms);if (!result.Success){var failures = result.Diagnostics.Where(diagnostic =>diagnostic.IsWarningAsError ||diagnostic.Severity == DiagnosticSeverity.Error);error = string.Join("\n", failures.Select(f => f.GetMessage()));return false;}ms.Seek(0, SeekOrigin.Begin);var assembly = Assembly.Load(ms.ToArray());_compiledScripts[scriptId] = assembly;return true;}}catch (Exception ex){error = ex.Message;return false;}}private string GenerateControlAccessCode(){if (_controlManager == null) return "";var sb = new StringBuilder();// 生成每个控件的访问属性foreach (var controlName in _controlManager.GetAllControlNames()){var designControl = _controlManager.FindControlByName(controlName);if (designControl?.InnerControl != null){var controlType = designControl.InnerControl.GetType().Name;sb.AppendLine($@"public {controlType}{controlName}{{get{{if (_controls != null && _controls.ContainsKey(""{controlName}""))return _controls[""{controlName}""] as {controlType};return null;}}}}");}}// 添加通用的查找方法sb.AppendLine(@"public Control FindControl(string name){if (_controls != null && _controls.ContainsKey(name))return _controls[name];return null;}public T FindControl<T>(string name) where T : Control{return FindControl(name) as T;}");return sb.ToString();}private MetadataReference[] GetMetadataReferences(){var references = new List<MetadataReference>();var addedAssemblies = new HashSet<string>();try{// 核心程序集列表var coreAssemblies = new[]{typeof(object), // System.Private.CoreLibtypeof(Console), // System.Consoletypeof(Control), // System.Windows.Formstypeof(MessageBox), // System.Windows.Formstypeof(System.Drawing.Color), // System.Drawingtypeof(System.Drawing.Point), // System.Drawing.Primitivestypeof(Dictionary<,>), // System.Collectionstypeof(Enumerable), // System.Linqtypeof(System.ComponentModel.Component), // System.ComponentModel.Primitivestypeof(System.ComponentModel.TypeConverter), // System.ComponentModel.TypeConvertertypeof(Encoding), // System.Text.Encoding.Extensionstypeof(System.Text.RegularExpressions.Regex) // System.Text.RegularExpressions};// 添加核心程序集foreach (var type in coreAssemblies){try{var location = type.Assembly.Location;if (!string.IsNullOrEmpty(location) && File.Exists(location) && !addedAssemblies.Contains(location)){references.Add(MetadataReference.CreateFromFile(location));addedAssemblies.Add(location);}}catch { }}// 添加当前程序集var currentAssembly = Assembly.GetExecutingAssembly();if (!string.IsNullOrEmpty(currentAssembly.Location) && !addedAssemblies.Contains(currentAssembly.Location)){references.Add(MetadataReference.CreateFromFile(currentAssembly.Location));addedAssemblies.Add(currentAssembly.Location);}// 尝试通过名称加载必要的程序集var requiredAssemblyNames = new[]{"System.Runtime","System.Private.CoreLib","mscorlib","System.ComponentModel.Primitives","System.ComponentModel.TypeConverter","System.ComponentModel","System.Drawing.Primitives","System.Collections","System.Collections.Concurrent","System.Text.Encoding.Extensions","System.Text.RegularExpressions","netstandard"};foreach (var assemblyName in requiredAssemblyNames){try{var assembly = Assembly.Load(assemblyName);var location = assembly.Location;if (!string.IsNullOrEmpty(location) && File.Exists(location) && !addedAssemblies.Contains(location)){references.Add(MetadataReference.CreateFromFile(location));addedAssemblies.Add(location);}}catch { }}// 从当前 AppDomain 加载的程序集中查找foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()){try{if (!assembly.IsDynamic &&!string.IsNullOrEmpty(assembly.Location) &&File.Exists(assembly.Location) &&!addedAssemblies.Contains(assembly.Location)){var name = assembly.GetName().Name;if (name.StartsWith("System.") ||name.StartsWith("Microsoft.") ||name.Equals("mscorlib") ||name.Equals("netstandard")){references.Add(MetadataReference.CreateFromFile(assembly.Location));addedAssemblies.Add(assembly.Location);}}}catch { }}Console.WriteLine($"Added {references.Count} assembly references for script compilation.");}catch (Exception ex){Console.WriteLine($"Error getting metadata references: {ex.Message}");// 最小引用集作为后备references.Clear();addedAssemblies.Clear();var fallbackAssemblies = new[]{typeof(object).Assembly.Location,typeof(Control).Assembly.Location,typeof(MessageBox).Assembly.Location};foreach (var location in fallbackAssemblies){if (!string.IsNullOrEmpty(location) && File.Exists(location)){references.Add(MetadataReference.CreateFromFile(location));}}}return references.ToArray();}public void ExecuteScript(string scriptId, Control sender, EventArgs e){if (_compiledScripts.TryGetValue(scriptId, out var assembly)){try{var type = assembly.GetType("ScriptClass");if (type == null){MessageBox.Show("无法找到脚本类", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);return;}var instance = Activator.CreateInstance(type);// 设置控件字典if (_controlManager != null){var controlDict = new Dictionary<string, Control>();foreach (var kvp in _controlManager.ControlsByName){controlDict[kvp.Key] = kvp.Value.InnerControl;}var setControlsMethod = type.GetMethod("SetControls");setControlsMethod?.Invoke(instance, new object[] { controlDict });}var method = type.GetMethod("Execute");if (method == null){MessageBox.Show("无法找到Execute方法", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);return;}method.Invoke(instance, new object[] { sender, e });}catch (Exception ex){MessageBox.Show($"脚本执行错误: {ex.Message}\n\n详细信息:\n{ex.StackTrace}","错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}}else{MessageBox.Show($"未找到脚本: {scriptId}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}}// 清理编译缓存的方法public void ClearCompiledScripts(){_compiledScripts.Clear();}// 获取所有已编译脚本的IDpublic IEnumerable<string> GetCompiledScriptIds(){return _compiledScripts.Keys;}// 测试编译功能public bool TestCompilation(out string error){var testCode = @"MessageBox.Show(""Test compilation successful!"");";return CompileScript("test", testCode, out error);}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。