zoukankan      html  css  js  c++  java
  • 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

    HearthbuddyTritonCommonCodeCompiler.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:UserscluDesktopGitHubHearthbuddyReleasein oslyncsc.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);
    }
  • 相关阅读:
    希望jQuery操作DOM文档,则必须确保DOM载入后开始执行
    Web全栈AngularJS
    Web全栈AngularJS
    Web全栈AngularJS
    KD-Tree
    KD-Tree
    KD-Tree
    KD-Tree
    如何提升自身实力
    如何提升自身实力
  • 原文地址:https://www.cnblogs.com/chucklu/p/11300734.html
Copyright © 2011-2022 走看看