Excellent Starting Platform! Patches Included!

Oct 6, 2011 at 5:57 PM
Edited Oct 17, 2011 at 3:26 PM

This was exactly what we needed to get around the (utterly ridiculous, IMNSHO) 260 character limit!  I made some mods to it, including the UNC fix that's on this site and, not knowing or seeing how to attach a code file, will insert a patchfile containing my changes instead.  These changes include:

  1. Remove the requirement for .NET 4 - it will now build and run fine on .NET 3.5.  No idea about other versions as 3.5 and 4 are what we use.
  2. Add long path unc support (copied from here).
  3. Added method (SetFileTime()) to set the file date / time.  It simply sets the creation time, last write and last access time to the same value as that is all we require.
  4. Added method (GetFileInfo())  to get file data, using a cloned version  of the FileInfo class (needed a new class since many of the members or properties of FileInfo are read-only).
  5. Adjust the Create and Delete (Directory) methods to iteratively manage directory trees.
  6. Added GetShortPathName method to get the short version of a long filename.
  7. Added some minor utility methods that were useful for what we needed.

I'm sure some of these the features are not complete, but they serve our purposes. Feel free to use, comment and improve - just post your updates here please so all can benefit!

 

--------------------------------------------8<----------------------------------------------------

*** Interop/NativeMethods.cs	Mon Jan 19 17:26:36 1970
--- Interop/NativeMethods.cs	Mon Jan 19 17:26:36 1970
***************
*** 9,20 ****
--- 9,23 ----
  namespace Microsoft.Experimental.IO.Interop {
  
      internal static class NativeMethods {
+         internal const int ERROR_SUCCESS = 0x0;
          internal const int ERROR_FILE_NOT_FOUND = 0x2;
          internal const int ERROR_PATH_NOT_FOUND = 0x3;
          internal const int ERROR_ACCESS_DENIED = 0x5;
          internal const int ERROR_INVALID_DRIVE = 0xf;
          internal const int ERROR_NO_MORE_FILES = 0x12;
+         internal const int ERROR_FILE_EXISTS = 0x50;
          internal const int ERROR_INVALID_NAME = 0x7B;
+         internal const int ERROR_BAD_PATHNAME = 0xA1;
          internal const int ERROR_ALREADY_EXISTS = 0xB7;
          internal const int ERROR_FILENAME_EXCED_RANGE = 0xCE;  // filename too long.
          internal const int ERROR_DIRECTORY = 0x10B;
***************
*** 27,32 ****
--- 30,36 ----
          internal const int MAX_LONG_PATH = 32000;
          internal const int MAX_ALTERNATE = 14;
          internal const string LongPathPrefix = @"\\?\";
+         internal const string LongPathUNCPrefix = @"\\?\UNC\";
  
          public const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
          public const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
***************
*** 56,61 ****
--- 60,90 ----
              internal string cAlternate;
          }
  
+         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+         public struct BY_HANDLE_FILE_INFORMATION {
+             internal FileAttributes dwFileAttributes;
+             internal FILETIME ftCreationTime;
+             internal FILETIME ftLastAccessTime;
+             internal FILETIME ftLastWriteTime;
+             internal int dwVolumeSerialNumber;
+             internal int nFileSizeHigh;
+             internal int nFileSizeLow;
+             internal int nNumberOfLinks;
+             internal int nFileIndexHigh;
+             internal int nFileIndexLow;
+ 
+             public FileInfoNew ToFileInfoNew(String path)
+             {
+                 FileInfoNew fi = new FileInfoNew(path);
+                 fi.Attributes = dwFileAttributes;
+                 fi.Length = (((long)nFileSizeHigh) << 32) | (uint)nFileSizeLow;
+                 fi.CreationTime = LongPathCommon.ConvertFILETIMEToDateTime(ftCreationTime);
+                 fi.LastAccessTime = LongPathCommon.ConvertFILETIMEToDateTime(ftLastAccessTime);
+                 fi.LastWriteTime = LongPathCommon.ConvertFILETIMEToDateTime(ftLastWriteTime);
+                 return fi;
+             }
+         }
+ 
          internal static int MakeHRFromErrorCode(int errorCode) {
              return unchecked((int)0x80070000 | errorCode);
          }
***************
*** 76,83 ****
          internal static extern bool FindClose(IntPtr hFindFile);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
!         internal static extern uint GetFullPathName(string lpFileName, uint nBufferLength,
!            StringBuilder lpBuffer, IntPtr mustBeNull);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
--- 105,111 ----
          internal static extern bool FindClose(IntPtr hFindFile);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
!         internal static extern uint GetFullPathName(string lpFileName, uint nBufferLength, StringBuilder lpBuffer, IntPtr mustBeNull);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
***************
*** 89,96 ****
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
!         internal static extern bool CreateDirectory(string lpPathName,
!            IntPtr lpSecurityAttributes);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
--- 117,123 ----
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
!         internal static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          [return: MarshalAs(UnmanagedType.Bool)]
***************
*** 111,115 ****
--- 138,153 ----
  
          [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          internal static extern int FormatMessage(int dwFlags, IntPtr lpSource, int dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr va_list_arguments);
+ 
+         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+         [return: MarshalAs(UnmanagedType.Bool)]
+         internal static extern bool SetFileTime(SafeFileHandle hFile, ref FILETIME lpCreationTime, ref FILETIME lpLastAccessTime, ref FILETIME lpLastWriteTime);
+ 
+         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+         [return: MarshalAs(UnmanagedType.Bool)]
+         internal static extern bool GetFileInformationByHandle(SafeFileHandle hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
+ 
+         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+         internal static extern uint GetShortPathNameW(string lpszLongPath, char[] lpszShortPath, int cchBuffer);
      }
  }
*** LongPathCommon.cs	Mon Jan 19 17:26:36 1970
--- LongPathCommon.cs	Mon Jan 19 17:26:36 1970
***************
*** 1,6 ****
  //     Copyright (c) Microsoft Corporation.  All rights reserved.
  using System;
! using System.Diagnostics.Contracts;
  using System.Globalization;
  using System.IO;
  using System.Runtime.InteropServices;
--- 1,6 ----
  //     Copyright (c) Microsoft Corporation.  All rights reserved.
  using System;
! using System.Diagnostics;
  using System.Globalization;
  using System.IO;
  using System.Runtime.InteropServices;
***************
*** 68,81 ****
              return false;
          }
  
!         private static string AddLongPathPrefix(string path) {
! 
!             return NativeMethods.LongPathPrefix + path;
          }
  
!         internal static string RemoveLongPathPrefix(string normalizedPath) {
  
!             return normalizedPath.Substring(NativeMethods.LongPathPrefix.Length);
          }
  
          internal static bool Exists(string path, out bool isDirectory) {
--- 68,97 ----
              return false;
          }
  
!         internal static string AddLongPathPrefix(string path)
!         {
!             if (path.StartsWith(@"\\"))
!             { // if we have been passed a UNC style path (server) prepend \\?\UNC\ but we need to replace the \\ with a single \
!                 return NativeMethods.LongPathUNCPrefix + path.Substring(2);
!             }
!             else //assume a standard path (ie C:\windows) and prepend \\?\ to it
!             {
!                 return NativeMethods.LongPathPrefix + path;
!             }
          }
  
!         internal static string RemoveLongPathPrefix(string normalizedPath)
!         {
!             if (normalizedPath.StartsWith(NativeMethods.LongPathUNCPrefix)) // if we have been supplied a path with the \\?\UNC\ prefix
!             {
!                 return @"\\" + normalizedPath.Substring(NativeMethods.LongPathUNCPrefix.Length);
!             }
!             else if (normalizedPath.StartsWith(NativeMethods.LongPathPrefix)) // if we have been supplied with the \\?\ prefix
!             {
!                 return normalizedPath.Substring(NativeMethods.LongPathPrefix.Length);
!             }
  
!             return normalizedPath;
          }
  
          internal static bool Exists(string path, out bool isDirectory) {
***************
*** 165,173 ****
  
              int bufferLength = NativeMethods.FormatMessage(NativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS | NativeMethods.FORMAT_MESSAGE_FROM_SYSTEM | NativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY, IntPtr.Zero, errorCode, 0, buffer, buffer.Capacity, IntPtr.Zero);
  
!             Contract.Assert(bufferLength != 0);
  
              return buffer.ToString();
          }
      }
  }
--- 181,207 ----
  
              int bufferLength = NativeMethods.FormatMessage(NativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS | NativeMethods.FORMAT_MESSAGE_FROM_SYSTEM | NativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY, IntPtr.Zero, errorCode, 0, buffer, buffer.Capacity, IntPtr.Zero);
  
!             Debug.Assert(bufferLength != 0);
  
              return buffer.ToString();
          }
+ 
+         internal static System.Runtime.InteropServices.ComTypes.FILETIME ConvertDateTimeToFILETIME(DateTime dateTime)
+         {
+             long ft = dateTime.ToFileTime();
+             System.Runtime.InteropServices.ComTypes.FILETIME fileTime = new System.Runtime.InteropServices.ComTypes.FILETIME();
+             fileTime.dwLowDateTime = (int)(ft & 0xFFFFFFFF);
+             fileTime.dwHighDateTime = (int)(ft >> 32);
+             return fileTime;
+         }
+ 
+         internal static DateTime ConvertFILETIMEToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME fileTime)
+         {
+             uint low = (uint)fileTime.dwLowDateTime;
+             long longFT = (((long)fileTime.dwHighDateTime) << 32) | low;
+             DateTime dateTime = DateTime.FromFileTime(longFT);
+             return dateTime;
+         }
+ 
      }
  }
*** LongPathDirectory.cs	Mon Jan 19 17:26:36 1970
--- LongPathDirectory.cs	Mon Jan 19 17:26:36 1970
***************
*** 14,20 ****
      public static class LongPathDirectory {
  
          /// 
!         ///     Creates the specified directory.
          /// 
          /// 
          ///     A  containing the path of the directory to create.
--- 14,20 ----
      public static class LongPathDirectory {
  
          /// 
!         ///     Iteratively creates the specified directory tree.
          /// 
          /// 
          ///     A  containing the path of the directory to create.
***************
*** 52,77 ****
          ///     
          ///      specifies a device that is not ready.
          /// 
!         /// 
!         ///     Note: Unlike , this method only creates 
!         ///     the last directory in .
!         /// 
!         public static void Create(string path) {
  
!             string normalizedPath = LongPathCommon.NormalizeLongPath(path);
  
!             if (!NativeMethods.CreateDirectory(normalizedPath, IntPtr.Zero)) {
  
!                 // To mimic Directory.CreateDirectory, we don't throw if the directory (not a file) already exists
!                 int errorCode = Marshal.GetLastWin32Error();
!                 if (errorCode != NativeMethods.ERROR_ALREADY_EXISTS || !LongPathDirectory.Exists(path)) {
!                     throw LongPathCommon.GetExceptionFromWin32Error(errorCode);
                  }
              }
          }
  
          /// 
!         ///     Deletes the specified empty directory.
          /// 
          /// 
          ///      A  containing the path of the directory to delete.
--- 52,122 ----
          ///     
          ///      specifies a device that is not ready.
          /// 
!         public static void Create(string path)
!         {
!             if (String.IsNullOrEmpty(path))
!             {
!                 throw new ArgumentException("Path cannot be an empty string.");
!             }
  
!             int startPos = 1;   // First part of the path to create.
  
!             // Split the given string into components which will have to be individually created.
!             String[] pathComponents = path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
  
!             // Get the first path component, either "c:" or "\\servername".
!             String partPath = pathComponents[0];
! 
!             // If the path is a UNC path, then add the share to the initial starting path.  
!             if (partPath.StartsWith(@"\\"))
!             {
!                 if (pathComponents.Length < 3)
!                 {
!                     throw new ArgumentException("Invalid path specified: " + path);
!                 }
! 
!                 // Add the share name.
!                 partPath = Path.Combine(partPath, pathComponents[1]);
!                 startPos = 2;
!             }
! 
!             // If the path is the root of a drive, then add the directoy separator char.
!             if (partPath.Contains(":"))
!             {
!                 if (pathComponents.Length < 2)
!                 {
!                     throw new ArgumentException("Invalid path specified: " + path);
!                 }
! 
!                 // Add the directory separator char here since Path.Combine will not add it if a drive specifier (ie: "C:") is given.
!                 // See Remarks in http://msdn.microsoft.com/en-us/library/fyy7a5kt.aspx
!                 // Also see http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#relative%5Fpaths
!                 partPath += Path.DirectorySeparatorChar;
!             }
! 
!             // Create the individual path components.
!             for (int i = startPos; i < pathComponents.Length; i++)
!             {
!                 // Add the path component to create.
!                 partPath = System.IO.Path.Combine(partPath, pathComponents[i]);
! 
!                 string normalizedPath = LongPathCommon.NormalizeLongPath(partPath, "partPath");
! 
!                 // Create the path.
!                 if (!NativeMethods.CreateDirectory(normalizedPath, IntPtr.Zero))
!                 {
!                     // To mimic Directory.CreateDirectory, we don't throw if the directory (not a file) already exists
!                     int errorCode = Marshal.GetLastWin32Error();
!                     if (errorCode != NativeMethods.ERROR_ALREADY_EXISTS || !LongPathDirectory.Exists(partPath))
!                     {
!                         throw LongPathCommon.GetExceptionFromWin32Error(errorCode);
!                     }
                  }
              }
          }
  
          /// 
!         ///     Iteratively deletes the specified empty directory tree.
          /// 
          /// 
          ///      A  containing the path of the directory to delete.
***************
*** 120,131 ****
          ///     
          ///      specifies a device that is not ready.
          /// 
!         public static void Delete(string path) {
  
              string normalizedPath = LongPathCommon.NormalizeLongPath(path);
  
!             if (!NativeMethods.RemoveDirectory(normalizedPath)) {
!                 throw LongPathCommon.GetExceptionFromLastWin32Error();
              }
          }
  
--- 165,217 ----
          ///     
          ///      specifies a device that is not ready.
          /// 
!         /// 
!         public static void Delete(string path)
!         {
!             if (String.IsNullOrEmpty(path))
!             {
!                 throw new ArgumentException("Path cannot be an empty string.");
!             }
! 
!             char[] dirSeps = new char[] { '\\', '/' };
  
              string normalizedPath = LongPathCommon.NormalizeLongPath(path);
  
!             // Get the minimum number of path separators in a valid string... will vary depending on whether it's a UNC path or not.
!             int minDirSepPos = 4;   // \\?\c:\dir
!             if (normalizedPath.Contains("UNC"))
!             {
!                 minDirSepPos = 6;   // \\?\UNC\server\share\dir
!             }
! 
!             // Get the minimum remaining string length once all required path components are accounted for.
!             int minLength = -1;
!             try
!             {
!                 for (int i = 0; i < minDirSepPos; i++)
!                 {
!                     minLength = normalizedPath.IndexOfAny(dirSeps, ++minLength);
!                 }
!             }
!             catch (ArgumentOutOfRangeException e)
!             {
!                 throw new ArgumentException("Invalid path specified: " + path);
!             }
! 
!             while (true)
!             {
!                 // Remove the path
!                 if (!NativeMethods.RemoveDirectory(normalizedPath))
!                 {
!                     throw LongPathCommon.GetExceptionFromLastWin32Error();
!                 }
! 
!                 normalizedPath = normalizedPath.Remove(normalizedPath.LastIndexOfAny(dirSeps));
! 
!                 if (normalizedPath.Length <= minLength)
!                 {
!                     break;
!                 }
              }
          }
  
***************
*** 255,261 ****
          /// 
          public static IEnumerable EnumerateDirectories(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, includeDirectories: true, includeFiles: false);
          }
  
          /// 
--- 341,347 ----
          /// 
          public static IEnumerable EnumerateDirectories(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, true, false);
          }
  
          /// 
***************
*** 356,362 ****
          /// 
          public static IEnumerable EnumerateFiles(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, includeDirectories: false, includeFiles: true);
          }
  
          /// 
--- 442,448 ----
          /// 
          public static IEnumerable EnumerateFiles(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, false, true);
          }
  
          /// 
***************
*** 458,464 ****
          /// 
          public static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, includeDirectories: true, includeFiles: true);
          }
  
          private static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, bool includeDirectories, bool includeFiles) {
--- 544,550 ----
          /// 
          public static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern) {
  
!             return EnumerateFileSystemEntries(path, searchPattern, true, true);
          }
  
          private static IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, bool includeDirectories, bool includeFiles) {
***************
*** 486,492 ****
                  if (handle == null)
                      yield break;
  
!                 do {
                      string currentFileName = findData.cFileName;
  
                      if (IsDirectory(findData.dwFileAttributes)) {
--- 572,578 ----
                  if (handle == null)
                      yield break;
  
!                 do { 
                      string currentFileName = findData.cFileName;
  
                      if (IsDirectory(findData.dwFileAttributes)) {
***************
*** 530,535 ****
--- 616,645 ----
          private static bool IsCurrentOrParentDirectory(string directoryName) {
  
              return directoryName.Equals(".", StringComparison.OrdinalIgnoreCase) || directoryName.Equals("..", StringComparison.OrdinalIgnoreCase);
+         }
+ 
+         /// 
+         /// Gets the parent directory of the specified file.
+         /// 
+         /// Path from which to extract the parent directory.
+         /// A string containing the root directory.
+         public static String GetParentDirectory(String path)
+         {
+             int dirSeparator = path.LastIndexOfAny(new char[] { '\\', '/' });
+             String dir = path.Remove(dirSeparator);
+             return dir;
+         }
+ 
+         /// 
+         /// Gets the root directory of the specified path
+         /// 
+         /// Path from which to extract the root directory.
+         /// A string containing the root directory.
+         public static String GetRootDirectory(String path)
+         {
+             int dirSeparator = path.IndexOfAny(new char[] { '\\', '/' });
+             String dir = path.Remove(dirSeparator);
+             return dir;
          }
      }
  }
*** LongPathFile.cs	Mon Jan 19 17:26:36 1970
--- LongPathFile.cs	Mon Jan 19 17:26:36 1970
***************
*** 7,12 ****
--- 7,41 ----
  
  namespace Microsoft.Experimental.IO {
  
+ 
+     /// 
+     /// An approximation of the standard .NET FileInfo class.
+     /// 
+     public class FileInfoNew
+     {
+         public FileAttributes Attributes { get; set; }
+         public DateTime CreationTime { get; set; }
+         public String Directory { get; set; }
+         public Boolean Exists { get; set; }
+         public String Extension { get; set; }
+         public String FullName { get; set; }
+         public DateTime LastAccessTime { get; set; }
+         public DateTime LastWriteTime { get; set; }
+         public long Length { get; set; }
+         public String Name { get; set; }
+ 
+         public FileInfoNew() { }
+ 
+         public FileInfoNew(String path)
+         {
+             this.Exists = true;
+             this.Extension = path.Substring(path.LastIndexOf('.') + 1);
+             this.FullName = LongPathCommon.RemoveLongPathPrefix(path);
+             this.Name = path.Substring(path.LastIndexOf('\\') + 1);
+             this.Directory = path.Substring(0, path.LastIndexOf('\\'));     // Remove the trailing '\'
+         }
+     }
+ 
      /// 
      ///     Provides static methods for creating, copying, deleting, moving, and opening of files
      ///     with long paths, that is, paths that exceed 259 characters.
***************
*** 464,469 ****
--- 493,697 ----
              SafeFileHandle handle = GetFileHandle(normalizedPath, mode, access, share, options);
  
              return new FileStream(handle, access, bufferSize, (options & FileOptions.Asynchronous) == FileOptions.Asynchronous);
+         }
+ 
+         /// 
+         /// Sets the file's Creation, LastAccess and LastWrite times.
+         /// 
+         /// A  containing the file whose times are to be set.
+         /// A  containing the time to assign to the file.
+         /// 
+         ///      is .
+         /// 
+         /// 
+         ///      is an empty string (""), contains only white 
+         ///     space, or contains one or more invalid characters as defined in 
+         ///     .
+         ///     
+         ///         -or-
+         ///     
+         ///      contains one or more components that exceed
+         ///     the drive-defined maximum length. For example, on Windows-based 
+         ///     platforms, components must not exceed 255 characters.
+         /// 
+         /// 
+         ///      exceeds the system-defined maximum length. 
+         ///     For example, on Windows-based platforms, paths must not exceed 
+         ///     32,000 characters.
+         /// 
+         /// 
+         ///     One or more directories in  could not be found.
+         /// 
+         /// 
+         ///     The caller does not have the required access permissions.
+         ///     
+         ///         -or-
+         ///     
+         ///      refers to a file that is read-only and 
+         ///     is not .
+         ///     
+         ///         -or-
+         ///     
+         ///      is a directory.
+         /// 
+         /// 
+         ///      refers to a file that is in use.
+         ///     
+         ///         -or-
+         ///     
+         ///      specifies a device that is not ready.
+         /// 
+         public static void SetFileTime(string path, DateTime fileDateTime)
+         {
+             string normalizedPath = LongPathCommon.NormalizeLongPath(path);
+ 
+             // Convert the DateTime to a FILETIME
+             System.Runtime.InteropServices.ComTypes.FILETIME fileTime = LongPathCommon.ConvertDateTimeToFILETIME(fileDateTime);
+ 
+             SafeFileHandle handle = GetFileHandle(normalizedPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.Asynchronous);
+             bool result = NativeMethods.SetFileTime(handle, ref fileTime, ref fileTime, ref fileTime);
+             handle.Close();
+ 
+             if (!result)
+             {
+                 throw LongPathCommon.GetExceptionFromLastWin32Error();
+             }
+         }
+ 
+         /// 
+         /// Gets the file's information incl size, creation time, etc.
+         /// 
+         /// A  containing the file whose information is to be retrieved.
+         /// 
+         ///      is .
+         /// 
+         /// 
+         ///      is an empty string (""), contains only white 
+         ///     space, or contains one or more invalid characters as defined in 
+         ///     .
+         ///     
+         ///         -or-
+         ///     
+         ///      contains one or more components that exceed
+         ///     the drive-defined maximum length. For example, on Windows-based 
+         ///     platforms, components must not exceed 255 characters.
+         /// 
+         /// 
+         ///      is less than 0.
+         /// 
+         /// 
+         ///      exceeds the system-defined maximum length. 
+         ///     For example, on Windows-based platforms, paths must not exceed 
+         ///     32,000 characters.
+         /// 
+         /// 
+         ///     One or more directories in  could not be found.
+         /// 
+         /// 
+         ///     The caller does not have the required access permissions.
+         ///     
+         ///         -or-
+         ///     
+         ///      refers to a file that is read-only and 
+         ///     is not .
+         ///     
+         ///         -or-
+         ///     
+         ///      is a directory.
+         /// 
+         /// 
+         ///      refers to a file that is in use.
+         ///     
+         ///         -or-
+         ///     
+         ///      specifies a device that is not ready.
+         /// 
+         public static FileInfoNew GetFileInfo(string path)
+         {
+             NativeMethods.BY_HANDLE_FILE_INFORMATION fileData;
+             string normalizedPath = LongPathCommon.NormalizeLongPath(path);
+ 
+             SafeFileHandle handle = GetFileHandle(normalizedPath, FileMode.Open, FileAccess.Read, FileShare.None, FileOptions.None);
+             bool result = NativeMethods.GetFileInformationByHandle(handle, out fileData);
+             handle.Close();
+ 
+             if (!result)
+             {
+                 throw LongPathCommon.GetExceptionFromLastWin32Error();
+             }
+ 
+             FileInfoNew fileInfo = fileData.ToFileInfoNew(path);
+             return fileInfo;
+         }
+ 
+         /// 
+         /// Retrieves the short path form of the specified path.
+         /// 
+         /// A  containing the file whose times are to be set.
+         /// 
+         ///      is .
+         /// 
+         /// 
+         ///      is an empty string (""), contains only white 
+         ///     space, or contains one or more invalid characters as defined in 
+         ///     .
+         ///     
+         ///         -or-
+         ///     
+         ///      contains one or more components that exceed
+         ///     the drive-defined maximum length. For example, on Windows-based 
+         ///     platforms, components must not exceed 255 characters.
+         /// 
+         /// 
+         ///      exceeds the system-defined maximum length. 
+         ///     For example, on Windows-based platforms, paths must not exceed 
+         ///     32,000 characters.
+         /// 
+         /// 
+         ///     One or more directories in  could not be found.
+         /// 
+         /// 
+         ///     The caller does not have the required access permissions.
+         ///     
+         ///         -or-
+         ///     
+         ///      refers to a file that is read-only and 
+         ///     is not .
+         ///     
+         ///         -or-
+         ///     
+         ///      is a directory.
+         /// 
+         /// 
+         ///      refers to a file that is in use.
+         ///     
+         ///         -or-
+         ///     
+         ///      specifies a device that is not ready.
+         /// 
+         public static String GetShortPath(string path)
+         {
+             string normalizedPath = LongPathCommon.NormalizeLongPath(path);
+ 
+             // First obtain the size needed by passing NULL and 0.
+             uint length = NativeMethods.GetShortPathNameW(normalizedPath, null, 0);
+             if (length == 0)
+             {
+                 throw LongPathCommon.GetExceptionFromLastWin32Error();
+             }
+ 
+             // Allocate the correct buffer length.
+             char[] buffer = new char[length];
+ 
+             // And populate it with the full short path.
+             uint result = NativeMethods.GetShortPathNameW(normalizedPath, buffer, buffer.Length);
+             if (result == 0)
+             {
+                 throw LongPathCommon.GetExceptionFromLastWin32Error();
+             }
+ 
+             String shortPath = new String(buffer, 0, (int)result);
+             return LongPathCommon.RemoveLongPathPrefix(shortPath);
          }
  
          [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification="False positive")]

--------------------------------------------8<----------------------------------------------------

Sep 7, 2012 at 5:51 AM

Hi, I think the following part of LongPathDirectory.Create won't work:

String[] pathComponents = path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); ! // Get the first path component, either "c:" or "\\servername". ! String partPath = pathComponents[0]; ! ! // If the path is a UNC path, then add the share to the initial starting path. ! if (partPath.StartsWith(@"\\"))

partPath will never start with two backslashes, because the split threw those away. So any UNC path is becoming a relative path.

Sep 18, 2012 at 8:46 AM

Wait... if I want to delete the directory C:\temp\a\b, it will delete C:\temp\a too? And C:\temp as well? Why?