2009-09-28 9 views
23

क्या कोई फ़ाइल वास्तविक है या प्रतीकात्मक लिंक है, तो सी # का उपयोग करने का कोई तरीका है?जांचें कि कोई फ़ाइल वास्तविक है या प्रतीकात्मक लिंक

मैंने एमएसडीएन डब्ल्यू 32 डॉक्स (http://msdn.microsoft.com/en-us/library/aa364232(VS.85).aspx) के माध्यम से खोला है, और इसे जांचने के लिए कुछ भी नहीं मिला है। मैं यहां से CreateSymbolicLink का उपयोग कर रहा हूं, और यह ठीक काम कर रहा है।

उत्तर

18

मैं कुछ source code for symlinks posted on my blog है कि आप के लिए अनुमति देगा है:

  • सिमलिंक
  • जांच एक रास्ता एक सिमलिंक
  • एक सिमलिंक का लक्ष्य पुनः प्राप्त है या नहीं बनाने

यह भी होता है एनयूनीट टेस्ट केस, जिन्हें आप विस्तारित करना चाहते हैं।

भावपूर्ण सा है:

private static SafeFileHandle getFileHandle(string path) 
{ 
    return CreateFile(path, genericReadAccess, shareModeAll, IntPtr.Zero, openExisting, 
     fileFlagsForOpenReparsePointAndBackupSemantics, IntPtr.Zero); 
} 

public static string GetTarget(string path) 
{ 
    SymbolicLinkReparseData reparseDataBuffer; 

    using (SafeFileHandle fileHandle = getFileHandle(path)) 
    { 
     if (fileHandle.IsInvalid) 
     { 
      Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
     } 

     int outBufferSize = Marshal.SizeOf(typeof(SymbolicLinkReparseData)); 
     IntPtr outBuffer = IntPtr.Zero; 
     try 
     { 
      outBuffer = Marshal.AllocHGlobal(outBufferSize); 
      int bytesReturned; 
      bool success = DeviceIoControl(
       fileHandle.DangerousGetHandle(), ioctlCommandGetReparsePoint, IntPtr.Zero, 0, 
       outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); 

      fileHandle.Close(); 

      if (!success) 
      { 
       if (((uint)Marshal.GetHRForLastWin32Error()) == pathNotAReparsePointError) 
       { 
        return null; 
       } 
       Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
      } 

      reparseDataBuffer = (SymbolicLinkReparseData)Marshal.PtrToStructure(
       outBuffer, typeof(SymbolicLinkReparseData)); 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(outBuffer); 
     } 
    } 
    if (reparseDataBuffer.ReparseTag != symLinkTag) 
    { 
     return null; 
    } 

    string target = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer, 
     reparseDataBuffer.PrintNameOffset, reparseDataBuffer.PrintNameLength); 

    return target; 
} 

है:

  • ओपन के साथ CreateFile()
  • कॉल DeviceIoControl() फ़ाइल रिपार्स पॉइंट डेटा प्राप्त करने के (नोट: यह एक जंक्शन बिंदु हो सकता है !)
  • निरीक्षण के लिए returned data structure देखें। reparse tag आपको बताएगा कि यह एक जंक्शन बिंदु या प्रतीकात्मक लिंक है या नहीं। यह सब आप करना चाहते हैं।
+0

यदि यह संभव है, तो क्या आप यहां पूरा कोड पेस्ट कॉपी कर सकते हैं, ब्लॉन्ग में जाने की आवश्यकता है, अन्यथा संकलित नहीं होगा? – TarmoPikaro

+0

यह कोड अब एक [NuGet पैकेज] है (https://www.nuget.org/packages/SymbolicLinkSupport/) और [गिटहब पर है] (https://github.com/michaelmelancon/symboliclinksupport)। –

0

GetFileInformationByHandle एक BY_HANDLE_FILE_INFORMATION संरचना है जो एक क्षेत्र dwFileAttributes जहां बिट्स फ़ाइल की विशेषताएं (विवरण here) के बारे में जानकारी के साथ स्थापित कर रहे हैं है भरता है। विशेष रूप से, मुखौटा पर थोड़ा देखो ...:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

एक फ़ाइल या निर्देशिका एक जुड़े रिपार्स पॉइंट, या कोई फ़ाइल कि एक प्रतीकात्मक कड़ी है है।

+0

मैं System.IO.File.GetAttributes() विधि है, जो मैं लागू इस पर विश्वास का उपयोग कर की कोशिश की है, लेकिन यह केवल जंक्शन अंक पर काम करने लगता है, और नहीं प्रतीकात्मक लिंक। – mattdwen

+0

क्या आप स्वयं syscall कोशिश कर सकते हैं? मेरे पास यह कोशिश करने के लिए हाथ में कोई Vista इंस्टॉल नहीं है। –

+0

वही बात - 32 प्राप्त करना, जो केवल पुरालेख है। मुझे पता चला है कि मुझे इस विधि को निरस्त करना पड़ सकता है और वैसे भी हार्ड लिंक का उपयोग करना पड़ सकता है, लेकिन इसे समझना अच्छा होगा। – mattdwen

1

ओवरफ्लो प्रश्न स्टैक करने के लिए this answer के अनुसार पता लगाएँ कि क्या एक फ़ाइल PowerShell में एक प्रतीकात्मक कड़ी, फ़ाइल के लिए System.IO.FileAttributes (File.GetAttributes के माध्यम से) हो रही है, और परीक्षण ReparsePoint बिट के लिए है का पता लगाएं, काम करता है। यदि बिट सेट किया गया है, तो यह एक सिग्नलिंक या एक जंक्शन बिंदु है। यदि नहीं, तो यह एक नियमित फ़ाइल (या हार्डलिंक) है।

+0

फिर से, ReparsePoint पर भरोसा पर्याप्त नहीं है। – Joshua

7

यहां फाइलों और निर्देशिकाओं के लिंक से फ़ाइलों और निर्देशिकाओं को अलग करने का एक उदाहरण दिया गया है।

या तो फ़ाइलों या निर्देशिकाओं के लिंक उनके लक्ष्यों से अलग अपनी विशेषताओं (निर्माण तिथि, अनुमतियां) को बनाए रखते हैं।

फ़ाइल लिंक को हटाया जा सकता है (उदा। "डेल" का उपयोग करके) लक्ष्य फ़ाइल को प्रभावित किए बिना।

निर्देशिका लिंक को हटाए बिना निर्देशिका लिंक हटाया जा सकता है (उदा। "Rmdir")। "Rd/s" का उपयोग करते समय सावधानी बरतें। यह निर्देशिका लिंक लक्ष्य को हटा देगा।

कुंजी FileAttributesFileInfo और DirectoryInfo दोनों में चेक करने के लिए ध्वज FileAttributes.ReparsePoint है।

static void Main(string[] args) { 
FileInfo file_info = new FileInfo(args[0]); 
DirectoryInfo directory_info = new DirectoryInfo(args[0]); 

bool is_file = file_info.Exists; 
bool is_directory = directory_info.Exists; 

if (is_file) { 
    Console.WriteLine(file_info.ToString() + " is a file"); 

    if (file_info.Attributes.HasFlag(FileAttributes.ReparsePoint)) 
     Console.WriteLine(args[0] + " is a Windows file link"); 
} 
else if (is_directory) { 
    Console.WriteLine(directory_info.ToString() + " is a directory"); 

    if (directory_info.Attributes.HasFlag(FileAttributes.ReparsePoint)) 
     Console.WriteLine(args[0] + " is a Windows directory link"); 
} 
+0

विज्ञापन की देखभाल डी विवरण? कोड-केवल कभी-कभी ठीक होता है लेकिन आपके उत्तर का वर्णन करने के लिए कुछ शब्द लंबे समय तक जा सकते हैं। –

+0

धन्यवाद Okuma.Scott –

+2

फिर से, FileAttributes.ReparsePoint पर निर्भर है पर्याप्त नहीं है। – konsolebox

20
private bool IsSymbolic(string path) 
{ 
    FileInfo pathInfo = new FileInfo(path); 
    return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint); 
} 
+2

यह स्वीकार्य उत्तर होना चाहिए। यह सरल, संक्षिप्त, और सीधे सवाल का जवाब देता है। –

+0

क्या इस समाधान के बारे में कुछ ऐसा है जो स्वीकार्य समाधान बनाम है क्योंकि यह बहुत अच्छा लगता है। –

+5

सिर्फ इसलिए कि फ़ाइल के साथ एक पछतावा बिंदु है, इसका मतलब यह नहीं है कि यह एक प्रतीकात्मक लिंक है। एक पछतावा बिंदु फ़ाइल से जुड़े कस्टम डेटा का एक मनमाना सेट है। यह निर्धारित करने के लिए कि क्या यह वास्तव में प्रतीकात्मक लिंक को परिभाषित करता है, आपको रिपर्स पॉइंट डेटा की आईडी का निरीक्षण करने की आवश्यकता है। यह जवाब झूठी सकारात्मकताओं को किसी भी समय रीपर पॉइंट के साथ वास्तविक फ़ाइल से मुकाबला करेगा। यहां देखें: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx –