2012-11-03 57 views
0

這看起來像是一個bug。但是,也許你們可以幫助我做出決定。這是Microsoft.CSharp.CSharpCodeProvider中的文件路徑解析錯誤嗎?

這是一個錯誤?

註釋的測試用例如下:在Windows

using System; 
using System.CodeDom.Compiler; 
using System.Diagnostics; 
using System.IO; 
using Microsoft.CSharp; 

namespace CompilerBugTestCase 
{ 
    internal static class Program 
    { 
     private const string DirectoryName = "TestSourceCode"; 
     private const string DirectoryNameTrailingSlash = DirectoryName + "/"; // This is intentionally defined with the wrong kind of slash 
     private const string FileName = "Test.cs"; 
     private const string FilePath = DirectoryNameTrailingSlash + FileName; // By composition, this includes the wrong kind of slash 

     private static void Main() 
     { 
      ShowItDoesWorkA(); 
      Console.WriteLine("ShowItDoesWorkA executed."); 

      ShowItDoesWorkB(); 
      Console.WriteLine("ShowItDoesWorkB executed."); 

      ShowItDoesNotWork(); 
      Console.WriteLine("ShowItDoesNotWork executed."); 

      ShowItDoesNotWorkSimple(); 
      Console.WriteLine("ShowItDoesWorkSimple executed."); 

      Console.WriteLine("Press [ ENTER ] to exit"); 
      Console.ReadLine(); 
     } 

     private static void Setup() 
     { 
      if (!Directory.Exists(DirectoryName)) 
      { 
       Directory.CreateDirectory(DirectoryName); 
      } 

      // Notice that this call has no problems 
      // It uses the wrong slash, too! 
      if (File.Exists(FilePath)) 
      { 
       File.Delete(FilePath); 
      } 

      // We're creating a file with the wrong slash here as well. 
      File.WriteAllText(FilePath, "using System; namespace TestCode { internal static class TestClass { public static void Main() { Console.WriteLine(\"I work!\"); } } }"); 
     } 

     private static void CompileFiles(string[] files) 
     { 
      CSharpCodeProvider compiler = new CSharpCodeProvider(); 
      CompilerParameters parameters = new CompilerParameters() 
      { 
       GenerateExecutable = false, 
       GenerateInMemory = true, 
       IncludeDebugInformation = false, 
       TreatWarningsAsErrors = true 
      }; 

      CompilerResults results = compiler.CompileAssemblyFromFile(parameters, files); 
      if (results.Errors.Count > 0) 
      { 
       // When looking at this exception, note the path it says it cannot find! 
       // You will see it did not translate the path correctly and actually chopped the directory out. 
       // Is that really the intended behavior? 
       Debug.Fail(results.Errors[0].ErrorText); 
      } 
     } 

     private static void ShowItDoesWorkA() 
     { 
      Setup(); 

      string[] files = Directory.GetFiles(DirectoryName); 
      CompileFiles(files); 
     } 

     private static void ShowItDoesWorkB() 
     { 
      Setup(); 

      DirectoryInfo directory = new DirectoryInfo(DirectoryName); 
      FileInfo[] files = directory.GetFiles(); 

      string[] paths = new string[files.Length]; 
      for (int i = 0; i < paths.Length; i++) 
      { 
       paths[i] = files[i].FullName; 
      } 

      CompileFiles(paths); 
     } 

     private static void ShowItDoesNotWork() 
     { 
      Setup(); 

      // Here we'll use the path with the wrong kind of slash. 
      // It picks up the file just fine. 
      string[] files = Directory.GetFiles(DirectoryNameTrailingSlash); 
      CompileFiles(files); 
     } 

     private static void ShowItDoesNotWorkSimple() 
     { 
      // This is the simplest test case. 
      // We hard code the path with the wrong kind of slash and it still crashes. 

      Setup(); 

      string[] files = new string[1] { FilePath }; 
      CompileFiles(files); 
     } 
    } 
} 

回答

3
private const string DirectoryNameTrailingSlash = DirectoryName + "/"; 

路徑分離字符是反斜線,"\\"。或者更確切地說,它是Path.DirectorySeparatorChar。現在Windows本身也嘗試將正斜槓解釋爲分隔符。然而,並不總是與其他代碼廣泛匹配。像這樣的片斷我在源代碼中發現了CodeDOMProvider類:

internal static bool TryGetProbableCoreAssemblyFilePath(CompilerParameters parameters, out string coreAssemblyFilePath) { 
     string multiTargetingPackRoot = null; 
     char[] pathSeperators = new char[] { Path.DirectorySeparatorChar }; 
     // etc.. 
    } 

這種代碼,當你使用一個正斜槓只是故障。最後但並非最不重要的一點,編譯選項以正斜槓傳遞給編譯器。像/reference

通過正確的方式解決您的問題,使用Path.Combine()。

+0

我在代碼中的評論中提到我有意使用正斜槓。我特別指出了這種不一致。我知道如何解決它。感謝您確認它「並不總是與其他代碼廣泛匹配」。我還注意到,我的問題是「我做錯了什麼?」,這表明我遇到了麻煩。這已被修復。 –

+0

這對於內存中的程序集是如何工作的?我收到類似的錯誤:http://stackoverflow.com/questions/28231162/adding-assemblies-to-buildmanager-using-codedom-causing-intermittent-errors –