2009-07-27 25 views
9

背景超出MAX_PATH訪問文件在C#/。NET

我需要使用.NET版本2.0的最高寫一個工具(使用的東西現成的不是這個客戶端的政治,商業的選擇,和機密性/信任原因)通過網絡將文件從一臺服務器遷移到另一臺服務器。這些服務器是本地團隊的文件服務器,某些團隊文件夾需要遷移到其他服務器以促進重組。基本思想是我們讀取每個文件並在幾小時內通過網絡進行流式傳輸,幾天之後數據將被遷移。文件權限需要保留。由於這需要幾天時間(我們正在談論幾個千兆字節的數據,對於某些團隊),我們需要每晚迭代文件並比較修改日期並更新那些已更改的日期。理論上,最終新服務器將擁有最新的文件副本,用戶可以切換到新服務器。這當然不是這麼簡單,但是我們有一個設計,我們認爲應該工作:)

的問題

所以理論上我們只要打開該文件,它流在網絡上,並把它寫在另一端,對嗎?可能是相當長的 - \ DATA \團隊股份\ DIVISION \ DEPARTMENT \用戶名球隊:

d::)

不幸的是,在服務器上自己,是在文件夾路徑,例如創建的文件共享\

對於每個用戶,該路徑映射到驅動器,例如它將共享爲\\ SERVER \ TEAMNAME並映射到T:驅動器。

這造成了T:驅動器中可見文件在MAX_PATH限制內的情況,但是在服務器本身查看時,它們超出了它的範圍。我們無法使用網絡共享訪問這些文件,因爲此工具需要是通用的,可以在數百臺這樣的服務器上運行,並且沒有標準方法可以確定哪些文件共享是我們應該移動的文件共享,哪些不是 - 存在甚至沒有命名規範標準。此外,偶爾還有其他股份的子股,所以我們超過了MAX_PATH的限制兩倍!

我知道使用「\\?\」前綴指定路徑的解決方法,該路徑將路徑視爲UNC路徑並允許理論最大值爲32k個字符。

此變通辦法是在Win32 API級別實現的,System.IO命名空間基本上只是圍繞原生Win32 API函數的一個薄包裝器,但是Microsoft在處理調用之前「有效」地實現了額外的(不正確的)驗證關閉到API。在這種情況下,.NET Framework拒絕這條路,因爲它聲稱'?'是一個無效的路徑字符。

所以我的問題是...有沒有一種方法,我沒有想到,這將允許我解決這個問題,而不必完全重寫幾乎整個System.IO命名空間,使負載的P/Invoke調用,只是爲了消除這個惱人的驗證?

回答

5

BCL團隊做了一個3部分的系列講述爲什麼選擇這些選項以及工作是什麼。如果你還沒有讀到但我建議你這樣做,因爲它是信息的關於這一主題的重要來源

+1

是的,我見過這個。他們推薦的解決方案就是我試圖避免說實話。當我們處理文件和目錄元數據,權限和文件內容時,這會觸發大量的API調用,我真的希望有人會有一個可行的解決方案,這意味着我不必在下個月花費pinvoke.net;) – 2009-07-27 21:17:34

+0

我自己和其他答案[這裏](http://stackoverflow.com/a/29605805/589059)建議一些包裝庫,你可以用它來處理長路徑。 – rkagerer 2015-04-13 13:35:56

1

應該很容易解決這個限制有位平臺的調用,假設你的軟件有必要的權限:

[DllImport("kernel32.dll", SetLastError = true)] 
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, 
    uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, 
    uint dwFlagsAndAttributes, IntPtr hTemplateFile); 

// Must close/dispose handle separately from FileStream since it's not owned by 
// that object when passed to constructor. 
using (SafeFileHandle h = CreateFile(longUncPath, GENERIC_WRITE, 0, IntPtr.Zero, 
     OPEN_EXISTING, 0, IntPtr.Zero)) 
{ 
    using (var fs = new FileStream(h, FileAccess.Read)) 
    { 
     // operations with FileStream object 
    } 
} 
4

我跑成一個第三方的解決方案,可以幫助:AlphaFS

0

我已經成功地使用下面的小腳本刪除目錄結構。 pushd使用UNC格式,它給你32K而不是260限制

set "folder=\\SERVER\SHARE\DIVISION\DEPARTMENT\NAME OF TEAM - COULD BE FAIRLY LONG\" 
pushd "%folder%" 
for /d %%i in ("*") do rmdir "%%i" /s /q 
popd