From 127315b7d996b7fb9567cf2c535309d0c198b543 Mon Sep 17 00:00:00 2001 From: Beast-ofcourse Date: Tue, 7 Jul 2026 11:47:10 +0530 Subject: [PATCH] fix(execute_code): skip phantom CodeDom BOM error from mcs compiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mono's mcs compiler emits a stray U+FEFF BOM character on stdout during compilation. CodeDom's CSharpCodeProvider misinterprets this as a compiler error (no ErrorNumber, ErrorText is just the BOM), causing HasErrors to be true and results.CompiledAssembly to be null — even though mcs exits 0 and wrote the DLL successfully. Fix: - Compile to a temp DLL path (GenerateInMemory=false + OutputAssembly) instead of relying on results.CompiledAssembly. - Skip phantom errors where ErrorNumber is empty and ErrorText is only BOM/whitespace. - Load the produced DLL via Assembly.Load(File.ReadAllBytes(...)) when no real errors exist. - Clean up the temp DLL in a finally block. Fixes #1186 --- MCPForUnity/Editor/Tools/ExecuteCode.cs | 50 +++++++++++++++++++------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/MCPForUnity/Editor/Tools/ExecuteCode.cs b/MCPForUnity/Editor/Tools/ExecuteCode.cs index 34d3f6679..5b9a49072 100644 --- a/MCPForUnity/Editor/Tools/ExecuteCode.cs +++ b/MCPForUnity/Editor/Tools/ExecuteCode.cs @@ -294,32 +294,58 @@ private static Assembly CodeDomCompile(string source, string[] assemblyPaths, ou } } + // Compile to a controlled DLL path instead of in-memory. mcs prints a stray BOM line on + // stdout that Mono's CodeDom can't parse, so it fabricates a bogus error (no error number, + // text is just the BOM) and refuses to surface the assembly — even though mcs exits 0 and + // wrote the DLL. We skip that bogus error and Assembly.Load the produced DLL ourselves. + string outputAssemblyPath = Path.Combine(Path.GetTempPath(), $"mcp-codedom-{Guid.NewGuid():N}.dll"); using (var provider = new CSharpCodeProvider()) { var parameters = new CompilerParameters { - GenerateInMemory = true, + GenerateInMemory = false, + OutputAssembly = outputAssemblyPath, GenerateExecutable = false, TreatWarningsAsErrors = false, CompilerOptions = "@\"" + responseFilePath + "\"", }; - var results = provider.CompileAssemblyFromSource(parameters, source); - - if (results.Errors.HasErrors) + try { + var results = provider.CompileAssemblyFromSource(parameters, source); + + bool hasRealErrors = false; foreach (CompilerError error in results.Errors) { - if (!error.IsWarning) - { - int userLine = Math.Max(1, error.Line - WrapperLineOffset); - errors.Add($"Line {userLine}: {error.ErrorText}"); - } + if (error.IsWarning) + continue; + + // The bogus BOM "error": no error number, text is just the BOM/whitespace. + string text = (error.ErrorText ?? "").Trim('\uFEFF', ' ', '\t', '\r', '\n'); + if (string.IsNullOrEmpty(error.ErrorNumber) && string.IsNullOrEmpty(text)) + continue; + + hasRealErrors = true; + int userLine = Math.Max(1, error.Line - WrapperLineOffset); + errors.Add($"Line {userLine}: {error.ErrorText}"); } - return null; - } - return results.CompiledAssembly; + if (hasRealErrors) + return null; + + if (!File.Exists(outputAssemblyPath)) + { + errors.Add("CodeDom reported success but produced no assembly."); + return null; + } + + return Assembly.Load(File.ReadAllBytes(outputAssemblyPath)); + } + finally + { + try { if (File.Exists(outputAssemblyPath)) File.Delete(outputAssemblyPath); } + catch { /* best effort cleanup */ } + } } } finally