On a Vista machine with the valid path C:\Users\David, calling Directory.GetFiles(@"C:\Users\David") throws the following ArgumentException when run as the David user, who can view the contents of the directory just fine in Windows Explorer:
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
The Vista machine happens to have been accessed by a Mac running MacFuse, so the directory contains a file that looks like it is named "._Icon" but must really contain some illegal characters. I believe this is the source of the error. I am left with the problem of what to do when Directory.GetFiles() throws an exception when it runs across a file name it does not like? Are there any alternate ways of listing a files contents that do not through such exception?
As for this particular file, I suspect the file name must contain some characters not displayed by Windows Explorer or the command-prompt:
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
And finally:
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
Looking at the file across SMB, it looks like the file is actually named "._Icon?". Each time I try to remove the file from the Mac, the file seems to immediately reappear.
Can you try listing the file using PInvoke FindFirstFile- see here. Does is cause simmillar issues?
The file information will be returned in the WIN32 FIND DATA struct. Then you call FindNextFile for each file until it doesn't return 0. In the struct you can use cFileName member get the file name. Check to see what's invalid in there.
My point is that this may return the fileinformation that Directory.GetFiles spews on.
here is a sample of its use:
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]