1

How can I enumerate files and folders with names more than 255 characters?

Directory.GetDirectories() and Directory.GetFiles() throws an exception.


Well, i've found a solution.

My task was to find the longest path in a folder. And here is my solution: 1) Define everything i need

    public const uint FILE_ATTRIBUTE_DIRECTORY = 0x10;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string cAlternateFileName;
    }

    public enum FINDEX_INFO_LEVELS
    { 
      FindExInfoStandard,
      FindExInfoBasic,
      FindExInfoMaxInfoLevel
    };

    public enum FINDEX_SEARCH_OPS { 
      FindExSearchNameMatch,
      FindExSearchLimitToDirectories,
      FindExSearchLimitToDevices
    };

    // dwAdditionalFlags:
    public const int FIND_FIRST_EX_CASE_SENSITIVE = 1;
    public const int FIND_FIRST_EX_LARGE_FETCH = 2;

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern IntPtr FindFirstFileEx(
        string lpFileName,
        FINDEX_INFO_LEVELS fInfoLevelId,
        out WIN32_FIND_DATA lpFindFileData,
        FINDEX_SEARCH_OPS fSearchOp,
        IntPtr lpSearchFilter,
        int dwAdditionalFlags);

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool FindClose(IntPtr hFindFile);

2) Function itself

    private static int GetMaxPathLength(string path)
    {
        Console.WriteLine(path);
        if (path.StartsWith(@"\\?\") == false)
            path = @"\\?\" + path;

        WIN32_FIND_DATA findData;
        FINDEX_INFO_LEVELS findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoStandard;
        int additionalFlags = 0;
        if (Environment.OSVersion.Version.Major >= 6)
        {
            findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic;
            additionalFlags = FIND_FIRST_EX_LARGE_FETCH;
        }

        IntPtr hFile = FindFirstFileEx(
            Path.Combine(path, "*.*"),
            findInfoLevel,
            out findData,
            FINDEX_SEARCH_OPS.FindExSearchNameMatch,
            IntPtr.Zero,
            additionalFlags);

        int maxRelativePathLength = 0;

        if (hFile.ToInt32() != -1)
        {
            do
            {
                int pathLength = 0;
                if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
                {
                    if (findData.cFileName.Equals(".") == false && findData.cFileName.Equals("..") == false)
                        pathLength = GetMaxPathLength(Path.Combine(path, findData.cFileName));
                }
                else
                {
                    pathLength = Path.Combine(path, findData.cFileName).Length;
                }

                if (maxRelativePathLength < pathLength)
                    maxRelativePathLength = pathLength;

            } while (FindNextFile(hFile, out findData));

            FindClose(hFile);
        }

        return maxRelativePathLength;
    }
Vadim
  • 471
  • 6
  • 15

0 Answers0