2009-07-27 11 views
9

पृष्ठभूमिMAX_PATH परे तक पहुँचना फ़ाइलें सी # में /। नेट

मैं, (उच्चतम पर नेट संस्करण 2.0 का उपयोग कर एक उपकरण लिखने के लिए शेल्फ से कुछ का उपयोग कर राजनीतिक, वाणिज्यिक के लिए इस ग्राहक के लिए एक विकल्प नहीं है की जरूरत है और गोपनीयता/ट्रस्ट कारणों) नेटवर्क पर एक सर्वर से दूसरे सर्वर पर फ़ाइलों को माइग्रेट करने के लिए। सर्वर स्थानीय टीमों के लिए फ़ाइल सर्वर हैं, और पुनर्गठन की सुविधा के लिए कुछ टीम फ़ोल्डरों को अन्य सर्वरों में माइग्रेट करने की आवश्यकता है। मूल विचार यह है कि हम प्रत्येक फ़ाइल को पढ़ते हैं और नेटवर्क पर इसे घंटों से बाहर स्ट्रीम करते हैं और कुछ दिनों के बाद डेटा माइग्रेट किया जाएगा। फ़ाइल अनुमतियों को संरक्षित करने की आवश्यकता है। चूंकि इसमें कुछ दिन लगेंगे (हम कुछ टीमों के लिए डेटा के कई गीगाबाइट्स से बात कर रहे हैं), हमें हर रात फाइलों पर फिर से प्रयास करने की आवश्यकता होती है और संशोधित तिथियों की तुलना करने और बदलने वाले लोगों को अपडेट करने की आवश्यकता होती है। सिद्धांत यह है कि आखिरकार नए सर्वर में फ़ाइलों की एक अद्यतित प्रतिलिपि होगी और उपयोगकर्ता नए सर्वर पर स्विच कर सकते हैं। यह निश्चित रूप से यह काफी सरल नहीं है, लेकिन हम एक डिजाइन हमें लगता है कि काम करना चाहिए :)

समस्या

तो सिद्धांत रूप में हम सिर्फ फ़ाइल को खोलने, नेटवर्क पर स्ट्रीम है, और इसे लिखने दूसरी तरफ, है ना? काफी लंबी हो सकता है - टीम के \ Data \ टीम शेयरों \ डिवीजन \ विभाग \ नाम:

डी: :)

दुर्भाग्य से, सर्वर पर खुद को, फ़ाइल भागों जैसे फ़ोल्डर पथ पर बनाए गए थे \

प्रत्येक उपयोगकर्ता के लिए, यह पथ ड्राइव पर मैप किया गया है, उदाहरण के लिए इसे \\ SERVER \ TEAMNAME के ​​रूप में साझा किया जाएगा और टी: ड्राइव पर मैप किया जाएगा।

इसने स्थिति को जन्म दिया है जहां टी: ड्राइव से दिखाई देने वाली फ़ाइलें MAX_PATH सीमा के भीतर हैं, हालांकि जब स्थानीय रूप से सर्वर पर स्थानीय रूप से देखा जाता है, तो वे इसके आगे जाते हैं। हम नेटवर्क शेयरों का उपयोग कर फ़ाइलों तक नहीं पहुंच सकते हैं क्योंकि इस उपकरण को सैकड़ों सर्वरों पर चलाने के लिए जेनेरिक होना आवश्यक है, और यह बताने का कोई मानक तरीका नहीं है कि कौन से फाइल शेयर हैं जिन्हें हमें आगे बढ़ाना चाहिए और जो नहीं हैं - वहां है कोई नामकरण सम्मेलन मानक भी नहीं। इसके अलावा, कभी-कभी अन्य शेयरों के उप-शेयर होते हैं और इसलिए हम MAX_PATH से अधिक बार सीमा पार करते हैं!

मुझे "\\? \" उपसर्ग का उपयोग करके पथ निर्दिष्ट करने के लिए कामकाज के बारे में पता है, जो पथ को यूएनसी पथ के रूप में मानता है और सैद्धांतिक अधिकतम 32k वर्णों की अनुमति देता है।

यह वर्कअराउंड Win32 API स्तर पर लागू किया गया है, सिस्टम.आईओ नेमस्पेस मूल रूप से मूल Win32 API फ़ंक्शंस के आसपास एक पतली आवरण है, हालांकि माइक्रोसॉफ्ट ने कॉल को सौंपने से पहले "मददगार" अतिरिक्त (गलत) सत्यापन लागू किया है एपीआई के लिए बंद। इस मामले में, .NET Framework पथ को अस्वीकार कर रहा है क्योंकि यह दावा करता है कि '?' एक अवैध पथ चरित्र है।

तो मेरा सवाल है ... क्या ऐसा कोई तरीका नहीं है जिसके बारे में मैंने सोचा नहीं है कि मुझे लगभग पूरी प्रणाली को पूरी तरह से लिखने के बिना इस पर काम करने की अनुमति होगी। आईओ नामस्थान, पी/Invoke का भार बनाना कॉल, बस इस कष्टप्रद सत्यापन को हटाने के लिए?

उत्तर

5

बीसीएल टीम ने एक 3 भाग श्रृंखला बनाई थी कि इन विकल्पों को क्यों बनाया गया था और आसपास के काम क्या हैं।आपको लगता है कि पढ़ने के लिए नहीं किया है फिर भी मैं आपको बस इतना सुझाव है के रूप में यह विषय के बारे में जानकारी का एक बड़ा स्रोत है

+1

हाँ के बजाय 32K देता है। मैंने इसे देखा है। उनका अनुशंसित समाधान वह है जो मैं ईमानदार होने से बचने की कोशिश कर रहा हूं। चूंकि हम फ़ाइल और निर्देशिका मेटाडेटा, अनुमतियों और फ़ाइल सामग्रियों से निपट रहे हैं, यह बहुत सी एपीआई कॉलों को हिट करता है, और मैं वास्तव में उम्मीद करता था कि किसी के पास एक व्यावहारिक समाधान होगा जिसका मतलब होगा कि मुझे अगले महीने खर्च नहीं करना पड़ेगा pinvoke.net;) –

+0

मेरे अपने और अन्य उत्तरों [यहां] (http://stackoverflow.com/a/29605805/589059) कुछ रैपर पुस्तकालयों का सुझाव देते हैं जिनका उपयोग आप लंबे पथ से निपटने के लिए कर सकते हैं। – rkagerer

1

यह काफी मंच का एक सा के साथ इस समस्या का कामचलाऊ समाधान करने के लिए आसान होना चाहिए आह्वान, यह मानते हुए अपने सॉफ़्टवेयर की आवश्यक अनुमति नहीं है: AlphaFS:

[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

जब मेरी पी/आमंत्रण परिभाषा वर्ग को विभिन्न आयातों, structs और स्थिरांक की 3000 लाइनों तक पहुंचाया गया था और मेरे पास अभी भी आवश्यक सभी कार्यक्षमता नहीं थीं, मैंने सोचा कि मैं पहले यहां आऊंगा और देख सकता हूं कि मुझे कुछ स्पष्ट याद आ रही है .. ऐसा नहीं लगता है :( –

+0

गोटो। और कोई मौजूदा तृतीय-पक्ष समाधान नहीं है? मुझे आश्चर्य है! –

+0

@बेन: मेरा उत्तर देखें। –

4

मैं एक तीसरे पक्ष के समाधान में मदद मिल सकती है कि में फंस गयी।

0

आप एक मूल निर्देशिका मानचित्रण subst.exe का उपयोग करके पथ को छोटा करने की कोशिश कर सकते (या जो भी एपीआई वह आंतरिक रूप से उपयोग करता है):

http://www.makeuseof.com/tag/how-to-map-a-local-windows-folder-to-a-drive-letter/

आदर्श रूप में आप दूर नक्शा था पथ के जितना संभव हो उतना ।

0

मुझे नीचे छोटी लिपि का उपयोग करके निर्देशिका संरचनाओं को हटाने में सफलता मिली है। पुशड यूएनसी प्रारूप का उपयोग करता है जो आपको 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 
संबंधित मुद्दे