【问题标题】:runtime code compilation gives error - process cannot access the file运行时代码编译给出错误 - 进程无法访问文件
【发布时间】:2014-10-30 11:02:55
【问题描述】:

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

当我第一次单击按钮时,它工作正常,但如果多次单击同一个按钮,则会出现错误“该进程无法访问 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());
        }
    }
}

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

谢谢,

【问题讨论】:

  • 有什么线索可以解决这个问题吗??

标签: c# compilation runtime ioexception


【解决方案1】:
  var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" },
                       "Example" + ".exe", true);

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

在卸载程序集之前不会释放锁。根据标准 .NET Framework 规则,在卸载主应用程序域之前不会发生这种情况。通常在程序结束时。

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

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

寻求简单的解决方案:

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

【讨论】:

  • 让我试试..上面的解决方案。
  • sia - 你要把奖金发给 Hans Passant 吗?
【解决方案2】:

您似乎在每次按下按钮时都在编译 Example.exe,并打开调试设置,以便每次编译时都会创建一个带有调试信息的 Examples.pdb 文件。

问题可能是第一个编译过程没有释放它对 Examples.pdb 的锁定,或者当您运行 Example.exe 时,Visual Studio 正在使用 Examples.pdb,因此您无法重新编译它。

这是我要检查的两件事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 2018-11-18
    • 1970-01-01
    • 2012-04-11
    相关资源
    最近更新 更多