2010-02-08 174 views
14

我試圖刪除一個文件夾,並且刪除由於包含長路徑的文件夾而失敗。我認爲我需要使用別的東西而不是dir.Delete(true),任何人都在之前穿過這座橋?C#刪除長路徑的文件夾

非常感謝

try 
{ 
var dir = new DirectoryInfo(@FolderPath); 
dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly; 
dir.Delete(true); 
} 
catch (IOException ex) 
{ 
MessageBox.Show(ex.Message); 
} 

這是有問題的路徑:教育\克里斯的未使用2006年TO07 \老4.Careers區 \服務器\共享\戴夫\私人\招聘\招聘埃德\樂趣招聘活動第1周30.10.06或6.11.06或13.11.06職位介紹和職業資源\職業領域&職位等級導師幫助頁[1] .doc

+0

有多長路徑: http://www.codinghorror.com/blog/archives /000729.html – 2010-02-08 16:23:17

+0

您是否嘗試使用unicode路徑調用win32函數? – sclarson 2010-02-10 14:40:24

回答

8

在Windows API中,路徑的最大長度是MAX_PATH,它被定義爲260個字符。路徑按以下順序組織:驅動器號,冒號,反斜槓,用反斜槓分隔的組件以及空終止字符,例如,D驅動器上的最大路徑爲D:\ < 256個字符> NUL。

幾個函數的Unicode版本允許最大路徑長度約爲32,000個字符,長度爲255個字符。要指定這種路徑,請使用「\?\」前綴。 32,000個字符的最大路徑是近似值,因爲「\?\」前綴可以擴展爲更長的字符串,並且擴展適用於總長度。

例如,「\?\ D:\」。要指定這樣的UNC路徑,請使用「\?\ UNC \」前綴。例如,「\?\ UNC \\」。這些前綴不被用作路徑本身的一部分。它們表示應該以最小的修改將路徑傳遞給系統,這意味着您不能使用正斜槓來表示路徑分隔符或表示當前目錄的句點。另外,不能使用「\?\」前綴和相對路徑。相對路徑僅限於MAX_PATH字符。

shell和文件系統可能有不同的要求。可以使用shell UI無法處理的API創建路徑。

C#(x)的語法(X)

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern bool DeleteFile(string path); 

有關類的更多信息,請參閱從http://msdn.microsoft.com/en-us/library/system

摘錄:

http://www.codinghorror.com/blog/archives/000729.html

http://msdn.microsoft.com/en-us/library/aa363915%28VS.85%29.aspx

+1

嗨,我剛剛嘗試過這一點,我得到了同樣的錯誤「無法找到部分路徑的長路徑和文件名'」。你知道還有什麼我可以嘗試嗎? 謝謝 – Jamie 2010-02-08 16:36:16

+0

這個作品我試過了,適合我的300字符長的路徑。 – 2010-02-17 21:26:59

+1

這不是\?\,它是\\?\。 – Henrik 2012-10-08 11:53:56

3

的260個字符的限制(I假設這是你遇到的問題)是Windows中的一個問題,而不是.NET中的問題,所以解決這個問題可能很困難。

可能能夠通過改變你的工作目錄,使得刪除的相對路徑少於260個字符來解決它;我不知道這是否會起作用。

即:

var curDir = Directory.GetCurrentDirectory(); 
Environment.CurrentDirectory = @"C:\Part\Of\The\Really\Long\Path"; 
Directory.Delete("Relative\Path\To\Directory"); 
Environment.CurrentDirectory = curDir; 
+0

你在Directory.Delete(「Relative \ Path \ To \ Directory」)中缺少@ – Simon 2010-10-21 05:39:42

+3

,這似乎不起作用 – Simon 2010-10-21 05:47:37

2

檢查的Win32 API:http://msdn.microsoft.com/en-us/library/aa363915%28VS.85%29.aspx

在那裏,它指出:「在這個函數的ANSI版本,名稱限制爲MAX_PATH字符,此限制擴展到32,767寬字符。 ,調用該函數的Unicode版本並將「\?\」添加到路徑中。「

添加的PInvoke:

using System; 
using System.Runtime.InteropServices; 
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool DeleteFile(string lpFileName); 

使用它:

public static void DeleteLong(string fileName) { 

    string LongName = @"\\?\" + fileName; 
    DeleteFile(formattedName); 
} 
+0

從Windows 10版本1607開始,對於此函數的unicode版本(DeleteFileW),可以選擇刪除MAX_PATH字符限制,而不預先添加「\\?\」。有關詳細信息,請參閱命名文件,路徑和命名空間的「最大路徑限制」部分。 – JJS 2017-02-08 13:23:18

4

最好的我已經到目前爲止,這是

public static class IOHelper 
{ 
    public static void DeleteDirectory(DirectoryInfo directoryInfo) 
    { 
     var emptyTempDirectory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "IOHelperEmptyDirectory")); 
     emptyTempDirectory.Create(); 
     var arguments = string.Format("\"{0}\" \"{1}\" /MIR", emptyTempDirectory.FullName, directoryInfo.FullName); 
     using (var process = Process.Start(new ProcessStartInfo("robocopy") 
              { 
               Arguments = arguments, 
               CreateNoWindow = true, 
               UseShellExecute = false, 
              })) 
     { 
      process.WaitForExit(); 
     } 
     directoryInfo.Delete(); 
    } 
} 
+0

如果你解釋一下robocopy是什麼以及爲什麼使用/ MIR – 2016-08-03 13:27:51

0

下面的鏈接顯示爲長.NET內部實現在System.IO中支持路徑支持,它不是通過Reflector生成的最簡單的讀取,但包含大量的示例與前面提到的Win32 API一起工作。

http://reflector.webtropy.com/default.aspx/[email protected]/[email protected]/untmp/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/IO/[email protected]/1305376/[email protected]

這將是很好,如果這個功能是可通過System.IO爲支撐顯然是有!

2

這是我使用刪除主目錄,其中長的路徑往往會出現:

public static void DirectoryDeleteLong(string directoryPath) 
{ 
    var emptyDirectory = new DirectoryInfo(Path.GetTempPath() + "\\TempEmptyDirectory-" + Guid.NewGuid()); 
    try 
    { 
     emptyDirectory.Create(); 
     using (var process = new Process()) 
     { 
      process.StartInfo.FileName = "robocopy.exe"; 
      process.StartInfo.Arguments = "\"" + emptyDirectory.FullName + "\" \"" + directoryPath + "\" /mir /r:1 /w:1 /np /xj /sl"; 
      process.StartInfo.UseShellExecute = false; 
      process.StartInfo.CreateNoWindow = true; 
      process.Start(); 
      process.WaitForExit(); 
     } 
     emptyDirectory.Delete(); 
     new DirectoryInfo(directoryPath).Attributes = FileAttributes.Normal; 
     Directory.Delete(directoryPath); 
    } 
    catch(IOException) { } 
} 

這類似於西蒙張貼的解決方案,而且:

  • 減少ROBOCOPY的高默認重試限制。
  • 將屬性重置爲directory.delete將在標記爲只讀的任何內容上失敗。
  • 創建一個唯一的空目錄名稱,以便與多個線程一起工作。
3

我不知道這個問題是否仍然開放,但我解決了這個問題。代碼是在win7上用VS2008開發的。這些都是我跟着去解決問題

  1. 步驟創建一個空VS C#項目
  2. 添加一個引用到這個COM對象:Microsoft腳本運行時
  3. 添加使用腳本;您使用列表
  4. 某處在你的代碼,創建一個類似的功能是:

    private static void DeletePathWithLongFileNames(string path) 
    { 
        var tmpPath = @"\\?\"+ path 
        FileSystemObject fso = new FileSystemObjectClass() as FileSystemObject; 
        fso.DeleteFolder(tmpPath, true); 
    } 
    

Path參數是要刪除的目錄。該函數將prepends unicode路徑簽名,創建一個FileSystemObject實例並刪除路徑及其所有內容。

  • 編譯該程序,啓動生成的。具有管理權限的exe文件(在Win7上以管理員身份運行),找出要刪除的目錄並在其上應用此功能。然後,觀看長文件名。

不用說,它是強大的...和危險的。大功率帶來巨大的責任:-)

0

我創建了一個託管的.Net庫來工作文件和文件夾。

https://github.com/DotNetIO

var fs = LocalFileSystem.Instance : FileSystem 

^^^^發生在國際奧委會

fs.GetDirectory(@"C:\\a very very long path ...\with\subdirs\and files.txt").Delete(); 

乾杯