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)

 

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);
}

 

转载于:https://www.cnblogs.com/chucklu/p/11300734.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现C#窗体化软件实时加载并执行CS文件中的函数,你可以使用C#的`CSharpCodeProvider`类来动态编译和执行代码。以下是一个简单的示例代码,演示如何在C#窗体应用程序中实现这个功能: 首先,在你的C#窗体应用程序中添加一个文本框和一个按钮。文本框用于输入要加载的CS文件的路径,按钮用于执行加载并执行CS文件的操作。在按钮点击事件的处理程序中,添加以下代码: ```csharp using System; using System.CodeDom.Compiler; using System.Reflection; using System.Windows.Forms; using Microsoft.CSharp; namespace YourNamespace { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void btnExecute_Click(object sender, EventArgs e) { string filePath = txtFilePath.Text; // 获取要加载的CS文件路径 CSharpCodeProvider codeProvider = new CSharpCodeProvider(); CompilerParameters parameters = new CompilerParameters(); parameters.GenerateExecutable = false; // 不生成可执行文件 parameters.GenerateInMemory = true; // 在内存中生成程序集 parameters.ReferencedAssemblies.Add("System.dll"); // 添加所需的引用程序集 CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, filePath); if (results.Errors.HasErrors) // 如果编译出错 { string errorMessage = string.Empty; foreach (CompilerError error in results.Errors) { errorMessage += $"{error.ErrorText} (Line: {error.Line})" + Environment.NewLine; } MessageBox.Show(errorMessage, "Compilation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Assembly assembly = results.CompiledAssembly; Type type = assembly.GetType("YourNamespace.YourClass"); // 修改为CS文件中的命名空间和类名 if (type != null) { dynamic instance = Activator.CreateInstance(type); instance.YourMethod(); // 修改为CS文件中的方法名 } } } } } ``` 在上述代码中,`txtFilePath`是文本框控件,用于输入要加载的CS文件的路径。`btnExecute`是按钮控件,用于执行加载并执行CS文件的操作。 当你点击按钮时,它将读取输入的CS文件路径,并使用`CSharpCodeProvider`类动态编译文件。如果编译出错,它将显示编译错误信息;如果编译成功,它将创建程序集并实例化CS文件中的类,然后调用相应的方法。 请注意,在CS文件中的命名空间和类名应与代码中的`YourNamespace.YourClass`相对应。你需要根据实际情况修改这些值。 这样,每当你在窗体应用程序中输入并点击按钮时,它都会实时加载并执行CS文件中的函数。如果加载的CS文件编译错误,它还会提示相关的编译问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值