运行时代码编译出现错误-进程无法访问文件 [英] runtime code compilation gives error - process cannot access the file

查看:117
本文介绍了运行时代码编译出现错误-进程无法访问文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小型Windows应用程序,在该应用程序中,用户输入代码,然后在运行时编译按钮单击事件代码。

I hava small windows app where user enter code and on button click event code is compiled at runtime.

当我第一次单击按钮时,它可以正常工作,但是如果多次单击同一按钮,则会出现错误,该进程无法访问Exmaple.pdb文件,因为它正在被另一个进程使用。 。下面是使用System.Linq的示例示例代码

When i click button 1st time it works fine but if click same button more than once it gives error "The process cannot access the Exmaple.pdb file because it is being used by another process.". Below is the example sample code

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

我该如何解决这个问题因此,如果我多次单击同一按钮,它应该可以正常工作。

how do i solve this issue so that if i click same button more than once.. it should work properly.

谢谢,

推荐答案

  var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" },
                       "Example" + ".exe", true);

您正在将输出文件明确命名为Example.exe。您还将获得Example.pdb(为代码生成的调试信息文件),并使用第三个 true 参数要求它。一旦使用 results.CompiledAssembly.GetType(),就会加载生成的程序集,这将锁住Example.exe。由于您已连接调试器,因此调试器将为程序集找到匹配的.pdb文件并加载并锁定它。

You are explicitly naming the output file to Example.exe. You'll also get Example.pdb, the debug info file generated for the code, you asked for it with the 3rd true argument. As soon as you use results.CompiledAssembly.GetType(), you'll load the generated assembly and that puts a lock on Example.exe. Since you have the debugger attached, the debugger will locate the matching .pdb file for the assembly and load and lock it.

在程序集被释放之前,不会释放锁定。卸载。按照标准的.NET Framework规则,只有在卸载主应用程序域后,才会发生这种情况。通常在程序结束时。

The locks will not be released until the assembly is unloaded. And by standard .NET Framework rules, this will not happen until your primary appdomain is unloaded. Usually at the end of your program.

因此,再次尝试编译代码将是失败的鲸鱼。编译器无法创建.pdb文件,该文件已被调试器锁定。省略 true 参数将无济于事,它现在将无法创建输出文件Example.exe。

So trying to compile code again is going to be a fail whale. The compiler cannot create the .pdb file, it is locked by the debugger. Omitting the true argument isn't going to help, it will now fail to create the output file, Example.exe.

您将需要当然解决这个问题。到目前为止,最简单的解决方案是命名输出程序集。 CSharpCodeProvider的默认行为是生成具有唯一随机名称的程序集,因此您始终会避免这种冲突。一种更高级的方法是创建一个辅助AppDomain来加载程序集,现在允许您在重新编译之前再次将其卸载。

You will need to tackle this differently of course. By far the simplest solution is to not name the output assembly. Default behavior is for CSharpCodeProvider to generate an assembly with a unique random name, you'll always avoid a collision that way. A more advanced approach is to create a secondary AppDomain to load the assembly, now allowing to unload it again before you recompile.

选择简单的解决方案:

  var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" });
  parameters.IncludeDebugInformation = true;
  parameters.GenerateExecutable = true;
  // etc..

这篇关于运行时代码编译出现错误-进程无法访问文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆