HearthBuddy CSharpCodeProvider 如何编译cs文件 升级编译器
源码
源码1
namespace Hearthbuddy.Windows
{
// Token: 0x02000041 RID: 65
public class MainWindow : Window, IComponentConnector
// Hearthbuddy.Windows.MainWindow // Token: 0x0600021B RID: 539 RVA: 0x0008A250 File Offset: 0x00088450 private static void smethod_1(string string_0, string string_1, IEnumerable<string> ienumerable_0) { try { using (CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider()) { CompilerParameters compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = true }; foreach (string value in ienumerable_0) { compilerParameters.ReferencedAssemblies.Add(value); } CompilerResults compilerResults = csharpCodeProvider.CompileAssemblyFromSource(compilerParameters, new string[] { string_1 }); if (compilerResults.Errors.Count > 0) { StringBuilder stringBuilder = new StringBuilder(); foreach (object obj in compilerResults.Errors) { CompilerError compilerError = (CompilerError)obj; stringBuilder.AppendFormat(string.Concat(new object[] { "Line number ", compilerError.Line, ", Error Number: ", compilerError.ErrorNumber, ", '", compilerError.ErrorText, ";" }), Array.Empty<object>()); stringBuilder.AppendLine(); } throw new Exception(stringBuilder.ToString()); } Type type = compilerResults.CompiledAssembly.GetType(string_0); object obj2 = Activator.CreateInstance(type); object obj3 = type.GetMethod("Execute").Invoke(obj2, new object[0]); if (obj3 != null) { MainWindow.ilog_0.Info(obj3); } } } catch (Exception exception) { MainWindow.ilog_0.Error("[Ui] An exception occurred:", exception); } }
源码2
Hearthbuddy\Triton\Common\CodeCompiler.cs
public CompilerResults Compile() { this.method_2(); this.method_3(); if (this.SourceFilePaths.Count != 0) { CompilerResults result; using (CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", string.Format(CultureInfo.InvariantCulture.NumberFormat, "v{0:N1}", this.CompilerVersion) } })) { csharpCodeProvider.Supports(GeneratorSupport.Resources); if (this.resourceWriter_0 != null) { this.resourceWriter_0.Close(); this.resourceWriter_0.Dispose(); this.resourceWriter_0 = null; } foreach (Stream stream in this.list_2) { try { stream.Close(); stream.Dispose(); } catch { } } this.list_2.Clear(); CompilerResults compilerResults = csharpCodeProvider.CompileAssemblyFromFile(this.Options, this.SourceFilePaths.ToArray()); if (!compilerResults.Errors.HasErrors) { this.CompiledAssembly = compilerResults.CompiledAssembly; } compilerResults.TempFiles.Delete(); foreach (string path in this.list_1) { try { File.Delete(path); } catch { } } this.list_1.Clear(); result = compilerResults; } return result; } if (this.resourceWriter_0 != null) { this.resourceWriter_0.Close(); this.resourceWriter_0.Dispose(); this.resourceWriter_0 = null; } foreach (Stream stream2 in this.list_2) { try { stream2.Close(); stream2.Dispose(); } catch { } } this.list_2.Clear(); foreach (string path2 in this.list_1) { try { File.Delete(path2); } catch { } } this.list_1.Clear(); return null; }
在CodeCompiler的构造函数中,调用了下面的方法。在编译之前,先删除CompiledAssemblies文件夹下已经编译好的文件。
// Triton.Common.CodeCompiler // Token: 0x0600155E RID: 5470 RVA: 0x000CE98C File Offset: 0x000CCB8C private static void smethod_1() { string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CompiledAssemblies"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } foreach (string path2 in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)) { try { File.Delete(path2); } catch (Exception) { } } foreach (string path3 in Directory.GetDirectories(path)) { try { Directory.Delete(path3); } catch (Exception) { } } if (!Directory.Exists(CodeCompiler.CompiledAssemblyPath)) { Directory.CreateDirectory(CodeCompiler.CompiledAssemblyPath); } }
问题
如下代码无法通过编译
using System; using System.Linq; using System.Xml.Linq; namespace HREngine.Bots { public class XmlHelper { private static XElement _cardDatabase; public static string GetCardNameByCardId(string filePath, string cardId) { if (_cardDatabase == null) { _cardDatabase = XElement.Load(filePath); } var tempTargetElement = _cardDatabase.Elements("Entity") .FirstOrDefault(x => x.Attribute("CardID")?.Value == cardId); var tempTargetElement2 = tempTargetElement?.Elements("Tag") .FirstOrDefault(x => x.Attribute("name")?.Value == "CARDNAME"); XElement targetElement = tempTargetElement2?.Element("enUS"); if (targetElement == null) { throw new Exception(string.Format("Can not find card by Id {0}", cardId)); } return targetElement.Value; } } }
"The type or namespace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly reference?)"
The type or namespace name 'Xml' does not exist in the namespace 'System' (are you missing an assembly reference?)
The type or namespace name 'XElement' could not be found (are you missing a using directive or an assembly reference?)
2019-08-04 18:06:56,506 [7] ERROR AssemblyLoader`1 (null) - [Reload] An exception occurred.
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\clu\Desktop\GitHub\HearthbuddyRelease\bin\roslyn\csc.exe'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.get_CompilerName()
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames)
at Triton.Common.CodeCompiler.Compile()
at Triton.Common.AssemblyLoader`1.Reload(String reason)
修复
之前的CSharpCodeProvider 是https://docs.microsoft.com/en-us/dotnet/api/microsoft.csharp.csharpcodeprovider?view=dotnet-plat-ext-3.1
把这个类替换成https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/ 里面的同名的类
Reload的逻辑
// Triton.Common.AssemblyLoader<T> // Token: 0x06001556 RID: 5462 RVA: 0x000CE6C0 File Offset: 0x000CC8C0 public void Reload(string reason) { this.ilog_0.Debug(string.Format("Reloading AssemblyLoader<{0}> - {1}", typeof(T), reason)); this.Instances = new List<T>(); if (!Directory.Exists(this.string_0)) { this.ilog_0.Error(string.Format("Could not Reload assemblies because the path \"{0}\" does not exist.", this.string_0)); return; } foreach (string path in Directory.GetDirectories(this.string_0)) { try { CodeCompiler codeCompiler = new CodeCompiler(path); CompilerResults compilerResults = codeCompiler.Compile(); if (compilerResults != null) { if (compilerResults.Errors.HasErrors) { foreach (object obj in compilerResults.Errors) { this.ilog_0.Error("Compiler Error: " + obj.ToString()); } } else { this.Instances.AddRange(new TypeLoader<T>(codeCompiler.CompiledAssembly, null)); } } } catch (Exception ex) { if (ex is ReflectionTypeLoadException) { foreach (Exception exception in (ex as ReflectionTypeLoadException).LoaderExceptions) { this.ilog_0.Error("[Reload] An exception occurred.", exception); } } else { this.ilog_0.Error("[Reload] An exception occurred.", ex); } } } using (List<T>.Enumerator enumerator2 = new TypeLoader<T>(null, null).GetEnumerator()) { while (enumerator2.MoveNext()) { AssemblyLoader<T>.Class229 @class = new AssemblyLoader<T>.Class229(); @class.gparam_0 = enumerator2.Current; if (!this.Instances.Any(new Func<T, bool>(@class.method_0))) { this.Instances.Add(@class.gparam_0); } } } if (this.eventHandler_0 != null) { this.eventHandler_0(this, null); } }
string_0的赋值
// Token: 0x06001551 RID: 5457 RVA: 0x000CE580 File Offset: 0x000CC780 public AssemblyLoader(string directory, bool detectFileChanges) { this.Instances = new List<T>(); this.string_0 = directory; this.bool_0 = detectFileChanges; if (this.bool_0) { this.fileSystemWatcher_0.Path = directory; this.fileSystemWatcher_0.Filter = "*.cs"; this.fileSystemWatcher_0.IncludeSubdirectories = true; this.fileSystemWatcher_0.EnableRaisingEvents = true; this.fileSystemWatcher_0.Changed += this.method_0; this.fileSystemWatcher_0.Created += this.method_1; this.fileSystemWatcher_0.Deleted += this.method_2; } this.Reload("Initializing"); }
method2在读取文件路径
// Triton.Common.CodeCompiler // Token: 0x06001573 RID: 5491 RVA: 0x000CF470 File Offset: 0x000CD670 private void method_2() { if (this.FileStructure == CodeCompiler.FileStructureType.Folder) { foreach (string string_ in Directory.GetFiles(this.SourcePath, "*.resx", SearchOption.AllDirectories)) { this.method_1(string_); } bool flag = false; foreach (string string_2 in Directory.GetFiles(this.SourcePath, "*.baml", SearchOption.AllDirectories)) { flag = true; this.method_0(string_2); } foreach (string text in Directory.GetFiles(this.SourcePath, "*.cs", SearchOption.AllDirectories)) { if (text.ToLowerInvariant().Contains(".g.cs")) { if (flag) { this.SourceFilePaths.Add(text); } } else if (text.ToLowerInvariant().Contains(".xaml.cs")) { if (flag) { this.SourceFilePaths.Add(text); } } else { this.SourceFilePaths.Add(text); } } return; } this.SourceFilePaths.Add(this.SourcePath); }
作者:Chuck Lu GitHub |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2015-08-05 C#中的异常处理
2015-08-05 AppDomain
2015-08-05 接口方法执行时的查找顺序
2015-08-05 log4net使用总结
2014-08-05 使用CLR Profiler查看C#运行程序的内存占用情况