Compruebe si un archivo es real o un enlace simbólico

¿Hay alguna manera de decir usando C # si un archivo es real o un enlace simbólico?

He buscado en los documentos de MSDN W32 ( http://msdn.microsoft.com/en-us/library/aa364232(VS.85).aspx ) y no encuentro nada para verificar esto. Estoy usando CreateSymbolicLink desde aquí, y está funcionando bien.

Tengo un código fuente para enlaces simbólicos publicado en mi blog que te permitirá:

  • crear enlaces simbólicos
  • comprobar si una ruta es un enlace simbólico
  • recuperar el objective de un enlace simbólico

También contiene casos de prueba NUnit, que es posible que desee extender.

El bocado carnoso 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:

  • Abra el archivo con CreateFile()
  • Llame a DeviceIoControl() para obtener los datos del punto de reanálisis (NOTA: ¡podría ser un punto de unión!)
  • Verifique la estructura de datos devuelta para inspeccionar. La etiqueta de reanálisis le dirá si es un punto de unión o un enlace simbólico. Esto puede ser todo lo que quieras hacer.
 private bool IsSymbolic(string path) { FileInfo pathInfo = new FileInfo(path); return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint); } 

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

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

Los enlaces de archivos se pueden eliminar (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.

El FileAttributes clave FileAttributes para comprobar 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"); } 

De acuerdo con esta respuesta a Stack Overflow question Averigüe si un archivo es un enlace simbólico en PowerShell , funciona System.IO.FileAttributes para el archivo (a través de File.GetAttributes ) y prueba para el bit ReparsePoint. 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).

GetFileInformationByHandle llena 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 aquí ). En particular, mira el bit en la máscara …

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

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

Demuestra que las respuestas anteriores no son confiables. Finalmente obtuve la solución correcta de MSDN :

Para determinar si un directorio especificado es una carpeta montada, primero llame a la función GetFileAttributes e inspeccione el indicador FILE_ATTRIBUTE_REPARSE_POINT en el valor de retorno para ver si el directorio tiene un punto de reanálisis asociado. Si lo hace, use las funciones FindFirstFile y FindNextFile para obtener la etiqueta de análisis en el miembro dwReserved0 de la estructura WIN32_FIND_DATA. Para determinar si el punto de reanálisis es una carpeta montada (y no alguna otra forma de punto de reanálisis), pruebe si el valor de la etiqueta es igual al valor IO_REPARSE_TAG_MOUNT_POINT. Para obtener más información, vea Puntos de análisis.