2009-07-27 25 views
9

BỐI CẢNHTruy cập các file ngoài MAX_PATH trong C# /. NET

tôi cần phải viết một công cụ sử dụng .NET phiên bản 2.0 ở mức cao nhất (sử dụng một cái gì đó ra khỏi kệ không phải là một lựa chọn cho khách hàng này cho chính trị, thương mại, và lý do bảo mật/tin cậy) để di chuyển các tệp từ máy chủ này sang máy chủ khác qua mạng. Các máy chủ là các máy chủ tệp cho các nhóm địa phương và một số thư mục nhóm cần được di chuyển sang các máy chủ khác để tạo điều kiện tổ chức lại. Ý tưởng cơ bản là chúng tôi đọc từng tệp và phát trực tuyến qua mạng ngoài giờ và sau một vài ngày dữ liệu sẽ được di chuyển. Quyền tệp cần được giữ nguyên. Vì điều này sẽ mất một vài ngày (chúng tôi đang nói đến vài gigabyte dữ liệu, đối với một số nhóm), chúng tôi cần lặp lại các tệp mỗi đêm và so sánh các ngày sửa đổi và cập nhật những thay đổi. Lý thuyết là cuối cùng máy chủ mới sẽ có một bản sao cập nhật của các tập tin và người dùng có thể chuyển sang máy chủ mới. Đó là tất nhiên không hoàn toàn đơn giản này, nhưng chúng tôi có một thiết kế chúng tôi nghĩ nên làm việc :)

CÁC VẤN ĐỀ

Vì vậy, về mặt lý thuyết chúng ta chỉ cần mở tập tin, dòng nó qua mạng, và viết nó ở đầu bên kia, phải không? :)

Thật không may, trên các máy chủ bản thân, cổ phần tập tin được tạo ra tại đường dẫn thư mục như:

D: \ Data \ Đội Cổ \ DIVISION \ SỞ \ TÊN CỦA TEAM - THỂ BE khá dài \

Đối với mỗi người dùng, đường dẫn này được ánh xạ tới một ổ đĩa, ví dụ: đường dẫn này sẽ được chia sẻ thành \\ SERVER \ TEAMNAME và ánh xạ tới ổ T :.

Điều này đã gây ra tình huống mà các tệp hiển thị từ ổ T: nằm trong giới hạn MAX_PATH, tuy nhiên khi được xem cục bộ trên máy chủ, chúng sẽ vượt xa nó. Chúng tôi không thể truy cập các tệp bằng cách sử dụng chia sẻ mạng vì công cụ này cần phải chung chung, để chạy trên hàng trăm máy chủ này và không có cách nào tiêu chuẩn để cho biết chia sẻ tệp nào là chúng tôi nên di chuyển và những tệp không phải - có thậm chí không có tiêu chuẩn quy ước đặt tên. Ngoài ra, đôi khi có các cổ phần phụ của các cổ phiếu khác và vì vậy chúng tôi vượt quá giới hạn MAX_PATH hai lần!

Tôi biết cách giải quyết để xác định đường dẫn sử dụng tiền tố "\\? \", Xử lý đường dẫn dưới dạng đường dẫn UNC và cho phép tối đa lý thuyết 32k ký tự.

Cách giải quyết này được thực hiện ở cấp API Win32, không gian tên System.IO (chủ yếu) về cơ bản chỉ là một trình bao bọc mỏng xung quanh các hàm Win32 API nguyên thủy, tuy nhiên Microsoft đã "trợ giúp" thực hiện xác thực (không chính xác) trước khi thực hiện cuộc gọi tắt API. Trong trường hợp này, .NET Framework đang từ chối đường dẫn vì nó tuyên bố rằng '?' là ký tự đường dẫn không hợp lệ. Vì vậy, câu hỏi của tôi là ... là có một cách tôi đã không nghĩ rằng sẽ cho phép tôi làm việc xung quanh điều này mà không cần phải viết lại hoàn toàn gần như toàn bộ không gian tên System.IO, làm cho một tải P/Gọi cuộc gọi, chỉ để loại bỏ xác nhận gây phiền nhiễu này?

Trả lời

5

Nhóm BCL đã thực hiện chuỗi 3 phần về chính xác lý do tại sao các lựa chọn này được thực hiện và công việc xung quanh là gì.Nếu bạn chưa đọc mà nhưng tôi đề nghị bạn làm như đó là một nguồn thông tin về đề tài này

+1

Vâng tôi đã thấy điều này. Giải pháp được đề xuất của họ là những gì tôi đang cố gắng để tránh trung thực. Vì chúng tôi đang xử lý siêu dữ liệu tệp và thư mục, quyền và nội dung tệp, số lượt truy cập này có rất nhiều cuộc gọi API và tôi thực sự hy vọng ai đó sẽ có giải pháp khả thi có nghĩa là tôi sẽ không phải chi tiêu vào tháng tiếp theo pinvoke.net;) –

+0

Câu trả lời của riêng tôi và các câu trả lời khác [ở đây] (http://stackoverflow.com/a/29605805/589059) đề xuất một số thư viện trình bao bọc mà bạn có thể sử dụng để xử lý các đường dẫn dài. – rkagerer

1

Nó sẽ được khá dễ dàng để làm việc xung quanh hạn chế này với một chút nền tảng gọi, giả sử phần mềm của bạn có các quyền cần thiết:

[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 
    } 
} 
+1

Khi lớp P/Invoke định nghĩa của tôi có khoảng 3000 dòng nhập, cấu trúc và hằng số và tôi vẫn không có tất cả các chức năng tôi cần, tôi nghĩ mình sẽ đến đây trước và xem có thiếu gì không. Có vẻ như không: ( –

+0

Gotcha. Và không có giải pháp của bên thứ ba hiện tại? Tôi ngạc nhiên! –

+0

@Ben: Xem câu trả lời của tôi. –

4

Tôi đã chạy vào một giải pháp của bên thứ ba có thể trợ giúp: AlphaFS.

0

Tôi đã xóa thành công cấu trúc thư mục bằng cách sử dụng tập lệnh nhỏ bên dưới. pushd sử dụng định dạng UNC cung cấp cho bạn 32K thay vì 260 giới hạn

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 
Các vấn đề liên quan