2014-10-30 53 views
4

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

我如何解決這個問題,所以,如果我點擊同一個按鈕不止一次..它應能正常工作。

感謝,

+1

任何線索..來解決這個問題? – sia 2014-10-30 14:47:47

回答

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

您明確將輸出文件命名爲Example.exe。你還會得到Example.pdb,這是爲代碼生成的調試信息文件,你用第三個參數真實。只要您使用results.CompiledAssembly.GetType(),就會加載生成的程序集,並將Example.exe鎖定。由於您已連接調試器,因此調試器將爲程序集找到匹配的.pdb文件並加載並鎖定它。

在卸載程序集之前,鎖將不會被釋放。通過標準的.NET Framework規則,這將不會發生,直到您的主appdomain被卸載。通常在程序結束時。

所以試圖再次編譯代碼將會是一條失敗的鯨魚。編譯器不能創建.pdb文件,它被調試器鎖定。省略true參數不會幫助,它現在將無法創建輸出文件Example.exe。

當然你需要解決這個問題。到目前爲止,最簡單的解決方案是而不是命名輸出組件。默認行爲是CSharpCodeProvider使用唯一的隨機名稱生成程序集,您將始終以這種方式避免衝突。更高級的方法是創建一個輔助AppDomain來加載程序集,現在允許在重新編譯之前再次卸載它。

去了簡單的解決方案:

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

讓我試試..以上解決方案。 – sia 2014-11-02 13:38:49

+0

謝謝..它正在工作.. – sia 2014-11-03 05:06:13

+0

sia - 你會獎勵Hans Passant的獎金嗎? – PhillipH 2014-11-08 13:33:35

2

看起來你是在每次按下按鈕上,這樣就產生了Examples.pdb文件的調試信息每次編譯時編譯Example.exe,與調試設置。

問題可能是第一次編譯過程沒有釋放它對Examples.pdb的鎖定,或者當您運行Example.exe時,Visual Studio正在使用Examples.pdb,因此您無法重新編譯它。

這些是我要檢查的兩件事。

相關問題