2009-09-28 16 views

risposta

18

ho qualche source code for symlinks posted on my blog che vi permetterà di:

  • creare link simbolici
  • verifica se un percorso è un collegamento simbolico
  • recuperare la destinazione di un link simbolico

contiene anche Casi di test NUnit, che potresti voler estendere.

Il bit carnosa è:

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; 
} 

Cioè:

  • Aprire il file con CreateFile()
  • chiamata DeviceIoControl() per ottenere i dati dei punti di analisi (NOTA: potrebbe essere un punto di giunzione !)
  • Controllare il returned data structure da ispezionare. Il reparse tag ti dirà se si tratta di un punto di giunzione o di un collegamento simbolico. Questo potrebbe essere tutto quello che vuoi fare.
+0

Se è possibile, si può copiare il codice completo qui incollato, è necessario andare in blocco, altrimenti non verrà compilato? – TarmoPikaro

+0

Questo codice è ora un [pacchetto NuGet] (https://www.nuget.org/packages/SymbolicLinkSupport/) e [è su GitHub] (https://github.com/michaelmelancon/symboliclinksupport). –

0

GetFileInformationByHandle riempie una struttura BY_HANDLE_FILE_INFORMATION con un campo dwFileAttributes in cui sono impostati bit con informazioni sugli attributi del file (dettagli here). In particolare, guardare il bit a maschera ...:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

un file o una directory che ha un associato punto di analisi, o un file di che è un link simbolico.

+0

Ho provato con il metodo() System.IO.File.GetAttributes, che credo implementa questo, ma sembra solo a lavorare su punti di giunzione, e non collegamenti simbolici. – mattdwen

+0

Puoi provare lo stesso syscall? Non ho installato Vista a portata di mano per provare questo da solo. –

+0

Stessa cosa - ottenere 32, che è solo archivio. Ho appena scoperto che potrei dover abortire questo metodo e comunque usare gli hard link, ma sarebbe bello capirlo. – mattdwen

1

Secondo this answer a Stack Overflow domanda Scoprire se un file è un link simbolico in PowerShell, ricevendo il System.IO.FileAttributes per il file (via File.GetAttributes), e test per il bit ReparsePoint, funziona. Se il bit è impostato, è un collegamento simbolico o un punto di congiunzione. In caso contrario, è un file normale (o hardlink).

+0

Ancora una volta, fare affidamento su ReparsePoint non è sufficiente. – Joshua

7

Ecco un esempio di differenziazione di file e directory da collegamenti a file e collegamenti a directory.

I collegamenti a file o directory mantengono i propri attributi (data di creazione, autorizzazioni) separati dai rispettivi obiettivi.

I collegamenti di file possono essere cancellati (ad esempio utilizzando "del") senza influire sul file di destinazione.

I collegamenti di directory possono essere rimossi (ad esempio "rmdir") senza influire sulla directory di destinazione. Fai attenzione quando usi "rd/s". Questo rimuoverà la destinazione del collegamento alla directory.

La chiave FileAttributes flag per il check in entrambi FileInfo e 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

Cura dell'annuncio d una descrizione? Il codice solo a volte va bene, ma poche parole per descrivere la tua risposta possono fare molto. –

+0

Grazie Okuma.Scott –

+2

Ancora, affidarsi a FileAttributes.ReparsePoint non è sufficiente. – konsolebox

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

Questa dovrebbe essere la risposta accettata. È semplice, conciso e risponde direttamente alla domanda. –

+0

C'è qualcosa che mi manca su questa soluzione rispetto alla soluzione accettata perché questo sembra molto più bello. –

+5

Solo perché un file ha un punto di analisi associato ad esso NON significa che sia un collegamento simbolico. Un punto di analisi è solo un insieme arbitrario di dati personalizzati associati a un file. È necessario esaminare l'ID dei dati del punto di analisi per determinare se effettivamente definisce un collegamento simbolico. Questa risposta darà falsi positivi ogni volta che incontra un file reale con punti di analisi. Vedi qui: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx –

Problemi correlati