2009-09-28 25 views

Respuesta

18

tengo algo de source code for symlinks posted on my blog que le permitirá:

  • crear enlaces simbólicos
  • comprobación de si un camino es un enlace simbólico
  • recuperar el objetivo de un enlace simbólico

Contiene también Casos de prueba NUnit, que es posible que desee extender.

El bit carnosa es:

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

Es decir:

  • Abrir el archivo con CreateFile()
  • llamada DeviceIoControl() para obtener los datos de puntos de reanálisis (NOTA: podría ser un punto de unión !)
  • Revisa el returned data structure para inspeccionar. El reparse tag le dirá si es un punto de unión o un enlace simbólico. Esto puede ser todo lo que quieras hacer.
+0

Si es posible, ¿puede copiar pegar aquí el código completo, necesita entrar en blong, de lo contrario no compilará? – TarmoPikaro

+0

Este código ahora es un [paquete NuGet] (https://www.nuget.org/packages/SymbolicLinkSupport/) y [está en GitHub] (https://github.com/michaelmelancon/symboliclinksupport). –

0

GetFileInformationByHandle rellena una estructura BY_HANDLE_FILE_INFORMATION que tiene un campo dwFileAttributes donde los bits se establecen con información sobre los atributos del archivo (detalles here). En particular, mira el bit en la máscara ...:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

Un archivo o directorio que tiene un punto de análisis asociado , o un archivo que es un enlace simbólico.

+0

He intentado usar el método() System.IO.File.GetAttributes, que creo que implementa este, pero sólo parece funcionar en los puntos de unión y no de enlaces simbólicos. – mattdwen

+0

¿Puedes probar el syscall en sí? No tengo la instalación de Vista a mano para probar esto yo mismo. –

+0

Lo mismo: obtener 32, que es solo archivo. Acabo de enterarme de que debo abortar este método y utilizar Hard Links de todos modos, pero sería bueno saberlo. – mattdwen

1

Según this answer apilar pregunta desbordamiento averiguar si un archivo es un enlace simbólico en PowerShell, conseguir la System.IO.FileAttributes para el archivo (a través de File.GetAttributes), y las pruebas para el bit reparsepoint, funciona. Si el bit está configurado, es un enlace simbólico o un punto de unión. Si no, es un archivo regular (o enlace permanente).

+0

De nuevo, depender de ReparsePoint no es suficiente. – Joshua

7

Aquí hay un ejemplo de diferenciación de archivos y directorios de enlaces a archivos y enlaces a directorios.

Los enlaces a archivos o directorios mantienen sus propios atributos (fecha de creación, permisos) separados de sus objetivos.

Los enlaces de archivos pueden eliminarse (por ejemplo, usando "del") sin afectar el archivo de destino.

Los enlaces de directorio se pueden eliminar (por ejemplo, "rmdir") sin afectar el directorio de destino. Tenga cuidado al usar "rd/s". Esto eliminará el destino del enlace de directorio.

La clave FileAttributes para marcar en FileInfo y DirectoryInfo es 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

Atención al anuncio d una descripción? El código solo a veces está bien, pero unas pocas palabras para describir su respuesta pueden ser muy útiles. –

+0

Gracias Okuma.Scott –

+2

De nuevo, depender de FileAttributes.ReparsePoint no es suficiente. – konsolebox

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

Esta debería ser la respuesta aceptada. Es simple, conciso y responde directamente la pregunta. –

+0

¿Hay algo que me falta sobre esta solución frente a la solución aceptada porque parece mucho mejor? –

+5

El hecho de que un archivo tenga un punto de análisis asociado no significa que sea un enlace simbólico. Un punto de reanálisis es solo un conjunto arbitrario de datos personalizados asociados con un archivo. Debe inspeccionar la ID de los datos del punto de reanálisis para determinar si realmente define un enlace simbólico. Esta respuesta dará falsos positivos cada vez que encuentre un archivo real con puntos de análisis. Vea aquí: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx –

Cuestiones relacionadas