Как обработать исключение, когда Directory.GetFiles () выдает исключение, когда находит имя файла, которое ему не «нравится»? - PullRequest
3 голосов
/ 27 мая 2009

На компьютере Vista с допустимым путем C: \ Users \ David, вызывая Directory.GetFiles (@ "C: \ Users \ David"), выдает следующее исключение ArgumentException при запуске от имени пользователя David, который может просматривать содержимое каталог просто отлично в проводнике Windows:

System.ArgumentException message: Illegal characters in path.
Argument: ""
Stack trace:
   at System.IO.Path.CheckInvalidPathChars(String path)
   at System.IO.Path.InternalCombine(String path1, String path2)
   at System.IO.Directory.InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption)
   at System.IO.Directory.GetFiles(String path, String searchPattern, SearchOption searchOption)
   at System.IO.Directory.GetFiles(String path)
   at Microsoft.Samples.XFileExplorer.ContentView.CreateContentDataTable(String CurrentFolder) in C:\Users\david\Downloads\MEF Preview 5\MEF Preview 5\Samples\XFileExplorer\XFileExplorer\ContentView.xaml.cs:line 108

Возможно, к компьютеру с Vista обращался Mac с MacFuse, поэтому каталог содержит файл, который выглядит так, как будто он называется "._Icon", но на самом деле должен содержать некоторые недопустимые символы. Я считаю, что это источник ошибки. Я остаюсь с проблемой того, что делать, когда Directory.GetFiles () выдает исключение, когда он сталкивается с именем файла, которое ему не нравится? Существуют ли альтернативные способы составления списка содержимого файлов, которые не проходят через такое исключение?

Что касается этого конкретного файла, я подозреваю, что имя файла должно содержать некоторые символы, не отображаемые в проводнике Windows или командной строке:

   C:\Users\david>dir ._Icon
   Volume in drive C is Bootcamp
   Volume Serial Number is XXXX-XXX

   Directory of C:\Users\david

   File Not Found

И наконец:

   C:\Users\david>dir ._Icon*
   Volume in drive C is Bootcamp
   Volume Serial Number is XXXX-XXX
   Directory of C:\Users\david

   05/25/2008  07:40 AM            43,296 ._Icon
           1 File(s)         43,296 bytes
           0 Dir(s)  58,950,623,232 bytes free

Глядя на файл через SMB, похоже, что файл на самом деле называется "._Icon?". Каждый раз, когда я пытаюсь удалить файл с Mac, файл, кажется, немедленно появляется снова.

Ответы [ 4 ]

1 голос
/ 28 мая 2009

Можете ли вы попробовать перечислить файл, используя PInvoke FindFirstFile - см. Здесь . Является ли причиной проблем с simmillar?

Информация о файле будет возвращена в структуре WIN32 FIND DATA . Затем вы вызываете FindNextFile для каждого файла, пока он не возвращает 0. В структуре вы можете использовать член cFileName для получения имени файла. Проверьте, что там недопустимо.

Моя точка зрения такова, что это может вернуть информацию о файле, которую издает Directory.GetFiles.

Вот пример его использования:

public const int MAX_PATH = 260;
 public const int MAX_ALTERNATE = 14;

[StructLayout(LayoutKind.Sequential)]
    public struct FILETIME {
    public uint dwLowDateTime;
    public uint dwHighDateTime;
 }; 

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
public struct WIN32_FIND_DATA {
    public FileAttributes dwFileAttributes;
    public FILETIME ftCreationTime; 
    public FILETIME ftLastAccessTime; 
    public FILETIME ftLastWriteTime; 
    public int nFileSizeHigh;
    public int nFileSizeLow;
    public int dwReserved0;
    public int dwReserved1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)] 
    public string cFileName; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)] 
    public string cAlternate; 
}

[DllImport("kernel32", CharSet=CharSet.Unicode)] 
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

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

private long RecurseDirectory(string directory, int level, out int files, out int folders) {
    IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    long size = 0;
    files = 0;
    folders = 0;
    Kernel32.WIN32_FIND_DATA findData;

    IntPtr findHandle;

    // please note that the following line won't work if you try this on a network folder, like \\Machine\C$
    // simply remove the \\?\ part in this case or use \\?\UNC\ prefix
    findHandle = Kernel32.FindFirstFile(@"\\?\" + directory + @"\*", out findData);
    if (findHandle != INVALID_HANDLE_VALUE) {

        do {
            if ((findData.dwFileAttributes & FileAttributes.Directory) != 0) {

                if (findData.cFileName != "." && findData.cFileName != "..") {
                    folders++;

                    int subfiles, subfolders;
                    string subdirectory = directory + (directory.EndsWith(@"\") ? "" : @"\") + 
                        findData.cFileName;
                    if (level != 0)  // allows -1 to do complete search.
                        {
                    size += RecurseDirectory(subdirectory, level - 1, out subfiles, out subfolders);

                    folders += subfolders;
                    files += subfiles;
                    }
                }
            }
            else {
                // File
                files++;

                size += (long)findData.nFileSizeLow + (long)findData.nFileSizeHigh * 4294967296;
            }
        } 
        while (Kernel32.FindNextFile(findHandle, out findData));
        Kernel32.FindClose(findHandle);

    }

    return size;
}

// [Sample by Kåre Smith] // [Minor edits by Mike Liddell]
1 голос
/ 02 августа 2010

Просто к вашему сведению ... то, что вы видите, это Resource Fork. Они сильно отличаются от ресурсов Windows и примерно аналогичны альтернативным потокам данных NTFS.

http://en.wikipedia.org/wiki/Resource_fork

Форк ресурса реализован во всех файловых системах, используемых для системных дисков Macintosh (MFS, HFS и HFS Plus). Наличие ветки ресурса позволяет легко хранить различную дополнительную информацию, например, позволяя системе отображать правильный значок для файла и открывать его без необходимости расширения файла в имени файла. Хотя доступ к вилке данных работает так же, как доступ к файлу в любой другой операционной системе - выберите файл, выберите смещение в байтах, прочитайте некоторые данные - доступ к вилке ресурса работает больше как извлечение структурированных записей из базы данных.

С сайта Microsoft sysinternals:

Файловая система NTFS предоставляет приложениям возможность создавать альтернативные потоки данных. По умолчанию все данные хранятся в основном безымянном потоке данных файла, но с помощью синтаксиса file: stream вы можете читать и записывать в альтернативы. Не все приложения написаны для доступа к альтернативным потокам, но вы можете продемонстрировать потоки очень просто. Сначала перейдите в каталог на диске NTFS из командной строки. Далее введите «echo hello> test: stream». Вы только что создали поток с именем 'stream', который связан с файлом 'test'. Обратите внимание, что когда вы смотрите на размер теста, он отображается как 0, и файл открывается пустым при открытии в любом текстовом редакторе. Чтобы увидеть ваш поток, введите 'more

0 голосов
/ 01 ноября 2010

Я знаю, что это немного устарело, но у меня точно такая же проблема с доступом к файловой системе OSX из Windows. DotNet выдает мне ошибку «недопустимые имена файлов», и причиной является нулевой байт файла Mac с именем icon, но с квадратом в конце имени файла.

Мое решение состояло в том, чтобы использовать немного кода VB6 и объекта файловой системы interop.scripting для вывода списка файлов таким образом.

FSO не обходится без этих недопустимых символов.

надеюсь, что это поможет кому-то.

0 голосов
/ 27 мая 2009

Как насчет того, чтобы просто удалить файл или переименовать его?

Серьезно, случается ли это достаточно часто, чтобы вам стоило написать специальный код для "исправления"?

...