sia*_*sia 5 c# runtime compilation ioexception
我hava小窗口应用程序,用户输入代码和按钮单击事件代码在运行时编译.
当我第一次单击按钮时它工作正常,但如果多次单击相同的按钮,则会出现错误"进程无法访问Exmaple.pdb文件,因为它正由另一个进程使用." .下面是示例示例代码
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "Example" + ".exe", true); //iloop.ToString() +
parameters.GenerateExecutable = true;
CompilerResults results = csc.CompileAssemblyFromSource(parameters,
@"using System.Linq;
class Program {
public static void Main(string[] args) {}
public static string Main1(int abc) {" + textBox1.Text.ToString()
+ @"
}
}");
results.Errors.Cast<CompilerError>().ToList().ForEach(error => Error = error.ErrorText.ToString());
var scriptClass = results.CompiledAssembly.GetType("Program");
var scriptMethod1 = scriptClass.GetMethod("Main1", BindingFlags.Static | BindingFlags.Public);
StringBuilder st = new StringBuilder(scriptMethod1.Invoke(null, new object[] { 10 }).ToString());
result = Convert.ToBoolean(st.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
我如何解决这个问题,以便如果我不止一次点击相同的按钮..它应该正常工作.
谢谢,
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" },
"Example" + ".exe", true);
Run Code Online (Sandbox Code Playgroud)
您明确地将输出文件命名为Example.exe.您还将获得Example.pdb,即为代码生成的调试信息文件,您使用第3个true参数请求它.一旦使用results.CompiledAssembly.GetType(),您将加载生成的程序集并锁定Example.exe.由于您附加了调试器,调试器将找到组件的匹配.pdb文件并加载并锁定它.
在卸载组件之前,锁不会被释放.通过标准的.NET Framework规则,在卸载主应用程序域之前不会发生这种情况.通常在程序结束时.
因此,尝试再次编译代码将成为失败的鲸鱼.编译器无法创建.pdb文件,它被调试器锁定.省略真正的参数不会有帮助,它现在将无法创建输出文件Example.exe.
当然,你需要以不同的方式解决这个问题.到目前为止,最简单的解决方案是不命名输出组件.默认行为是CSharpCodeProvider生成具有唯一随机名称的程序集,您将始终避免这种冲突.更高级的方法是创建辅助AppDomain来加载程序集,现在允许在重新编译之前再次卸载它.
寻求简单的解决方案:
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" });
parameters.IncludeDebugInformation = true;
parameters.GenerateExecutable = true;
// etc..
Run Code Online (Sandbox Code Playgroud)