2012-02-09 52 views
4

環境:C#,.NET 4.0和混合模式。Directory.EnumerateFiles和File.Exists忽略本機DLL文件

我有一個複雜的應用程序與幾個第三方依賴項。當我們收到應用程序崩潰的一些報告時,我們添加了一些完整性檢查,以確保遍歷程序集依賴關係存在所有依賴關係。不幸的是,這並不檢查我們的應用程序使用的本機DLL文件的存在。我們的預期解決方案是遍歷所有DLL名稱,並確保至少有一個具有該名稱的文件作爲完整性檢查。

的問題

兩者Directory.EnumerateFiles()和File.Exists()不能看到這些本機DLL任一。代碼重現此問題是因爲教科書「如何列出文件」那樣簡單:

foreach(string file in 
     Directory.EnumerateFiles(Environment.CurrentDirectory, "*.dll")) 
{ 
    string entry = Path.GetFileName(file); 
    if (! RequiredFiles.Contains(entry)) 
    { 
     /* Do error handling */ 
    } 
} 

在我列出的文件的目錄凝望,我可以看到我想要檢測的文件。它們不以任何方式標記爲系統文件。然而,不管我是否有過濾器文本,只列出了.NET DLL文件。我想更直接地重寫代碼段並令人沮喪地得到相同的結果:

foreach(string dependency in RequiredFiles) 
{ 
    string fileName = Environment.CurrentDirectory + '\\' + dependency; 
    if(! File.Exists(fileName)) 
    { /* do error handling */ } 
} 

我得到了同樣的確切結果。所有本機DLL文件似乎對.NET不可見。

問題

是什麼原因造成的?更重要的是,如果我甚至無法在文件系統中看到它們,我如何檢測本機DLL文件是否存在?

+0

你能在一個空白的項目重現此?我非常懷疑原生DLL是否真的是「隱形」的。這聽起來像是其他事情正在發生;錯誤的CurrentDirectory,某些類型的影子複製,64位操作系統文件系統重定向上的32位進程等。本機DLL可能會被ClickOnce部署忽略。像這樣的東西。 – 2012-02-09 20:33:21

回答

2
  • 做了一個名字爲自己的DLL,例如MySuperNiftyLibrary.dll。它可以只是一個重命名的文本文件。把它放在你正在看的文件夾中。再次運行代碼。看看是否列出了這個名字。如果這不能說服你,請創建一個具有獨特名稱的小型.NET類庫項目,並將其放入目錄中。

    沒有理由Directory.EnumerateFiles會篩選.NET DLL而不是其他類型的DLL,因此您不可能查看正確的目錄。

  • 但是,如果你是,那麼考慮你正在尋找的DLL是否在頂層目錄或子目錄中。 默認情況下,EnumerateFiles僅列出頂級目錄中的文件。要列出所有子目錄中的所有文件,你需要使用的EnumerateFiles此重載:

Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories)

+0

現在我不覺得自己像個白癡。畢竟我的檢查和三重檢查後,我確信我正在尋找正確的目錄。直到你發佈這個答案之後,我才發現我確實在看一個幾乎完全相同但不同的目錄。唯一缺少的文件是本機DLL ... – 2012-02-10 13:33:09

0

然後用外殼,這樣的事情應該工作:

  Shell32.Shell shl = null; 
      Shell32.Folder folder = null; 
      try 
      { 
       shl = new Shell32.Shell(); 
       folder = shl.NameSpace(Environment.CurrentDirectory); 
       foreach (Shell32.FolderItem file in folder.Items()) 
       { 
        if (!RequiredFiles.Contains(file.path)) 
        {/* do error handling */} 
       } 
      } 
      catch 
      { } 
      finally 
      { 
       if (folder != null) 
       { 
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder); 
        folder = null; 
       } 
       if (shl != null) 
       { 
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shl); 
        shl = null; 
       } 
      } 

UPDATE:如果你打算用這個在XP和新的操作系統,你需要引用的Shell32.dll(微軟殼牌控制和自動化)在XP上編譯一次,以便這樣的DLL被複制到您的項目。因爲從Vista或7的DLL不能在XP上工作,並且它與之相反。這是依賴於Shell腳本的更簡單的方法。否則,你可以直接與Shell API互操作,但它更復雜...

2

你確定你的工作目錄是正確的嗎?否則Environment.CurrentDirectory將不會指向您的預期。如果DLL文件在同一目錄下執行的代碼,那麼你可以做,而不是:

Assembly.GetExecutingAssembly().Location 
+0

檢查了路徑,它與我正在查看的路徑相同。 – 2012-02-09 20:09:47