C# 枚举引发异常的文件
我试图使用下面的代码枚举我计算机上的文件,但每次它碰到我没有读取权限的文件或目录时,都会抛出一个异常。是否有任何方法可以在抛出异常后继续搜索?我知道有些人也有类似的问题,但除了逐个检查每个文件/文件夹外,还有其他方法吗C# 枚举引发异常的文件,c#,file,C#,File,我试图使用下面的代码枚举我计算机上的文件,但每次它碰到我没有读取权限的文件或目录时,都会抛出一个异常。是否有任何方法可以在抛出异常后继续搜索?我知道有些人也有类似的问题,但除了逐个检查每个文件/文件夹外,还有其他方法吗 try { string[] files = Directory.GetFiles(@"C:\", *.*",SearchOption.AllDirectories); foreach (string file in files) { Con
try
{
string[] files = Directory.GetFiles(@"C:\", *.*",SearchOption.AllDirectories);
foreach (string file in files)
{
Console.WriteLine(file);
}
}
catch
{
}
谢谢你的帮助,因为这快把我逼疯了 就在今天,我遇到了同样的问题。我拼凑了以下代码。如果您想在实际产品中使用它,您可能需要改进错误处理。因为这是一个一次性的脚本,我不太在乎
static IEnumerable<string> EnumerateFilesRecursive(string root,string pattern="*")
{
var todo = new Queue<string>();
todo.Enqueue(root);
while (todo.Count > 0)
{
string dir = todo.Dequeue();
string[] subdirs = new string[0];
string[] files = new string[0];
try
{
subdirs = Directory.GetDirectories(dir);
files = Directory.GetFiles(dir, pattern);
}
catch (IOException)
{
}
catch (System.UnauthorizedAccessException)
{
}
foreach (string subdir in subdirs)
{
todo.Enqueue(subdir);
}
foreach (string filename in files)
{
yield return filename;
}
}
}
它首先枚举所有文件,将所有文件名存储在内存中,然后才显示它们。或者,您可以:
IEnumerable<string> files = EnumerateFilesRecursive(@"C:\");//Note that there is NO ToArray()
foreach (string file in files)
{
Console.WriteLine(file);
}
IEnumerable files=EnumerateFilesRecursive(@“C:\”)//请注意,没有ToArray()
foreach(文件中的字符串文件)
{
Console.WriteLine(文件);
}
它在枚举时写入,因此不需要同时将所有文件名保留在内存中。以下是一些基于Windows API的实用程序代码,它枚举文件系统条目而不引发/捕获异常 示例用法:
...
foreach (var fi in Utilities.EnumerateFileSystemEntries(@"c:\windows\system32", DirectoryEnumerateOptions.Recursive))
{
Console.WriteLine(fi.FullName);
}
...
实用程序类别:
[Flags]
public enum DirectoryEnumerateOptions
{
None = 0x0,
Recursive = 0x1,
ThrowErrors = 0x2, // if you really want it
ExpandEnvironmentVariables = 0x4,
}
public static class Utilities
{
public static IEnumerable<FileSystemInfo> EnumerateFileSystemEntries(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (directoryPath == null)
throw new ArgumentNullException(nameof(directoryPath));
if (!Path.IsPathRooted(directoryPath))
{
directoryPath = Path.GetFullPath(directoryPath);
}
return EnumerateFileSystemEntriesPrivate(directoryPath, options);
}
private static IEnumerable<FileSystemInfo> EnumerateFileSystemEntriesPrivate(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (!Directory.Exists(directoryPath))
yield break;
var findPath = Normalize(directoryPath, options.HasFlag(DirectoryEnumerateOptions.ExpandEnvironmentVariables));
if (!findPath.EndsWith("*"))
{
findPath = Path.Combine(findPath, "*");
}
var h = FindFirstFile(findPath, out var data);
if (h == INVALID_HANDLE_VALUE)
{
if (options.HasFlag(DirectoryEnumerateOptions.ThrowErrors))
throw new Win32Exception(Marshal.GetLastWin32Error());
yield break;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
do
{
if (!FindNextFile(h, out data))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_FILES)
{
FindClose(h);
break;
}
continue;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
}
while (true);
}
private static bool Include(ref WIN32_FIND_DATA data) => data.cFileName != "." && data.cFileName != "..";
private static FileSystemInfo ToInfo(ref WIN32_FIND_DATA data, string directoryPath)
{
if (data.fileAttributes.HasFlag(FileAttributes.Directory))
return new FileInfo(Path.Combine(directoryPath, data.cFileName));
return new DirectoryInfo(Path.Combine(directoryPath, data.cFileName));
}
private static string Normalize(string path, bool expandEnvironmentVariables)
{
if (path == null)
return null;
string expanded;
if (expandEnvironmentVariables)
{
expanded = Environment.ExpandEnvironmentVariables(path);
}
else
{
expanded = path;
}
if (expanded.StartsWith(_prefix))
return expanded;
if (expanded.StartsWith(@"\\"))
return _uncPrefix + expanded.Substring(2);
return _prefix + expanded;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", SetLastError = true)]
private static extern bool FindClose(IntPtr hFindFile);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
#pragma warning disable IDE1006 // Naming Styles
private const int ERROR_NO_MORE_FILES = 18;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
#pragma warning restore IDE1006 // Naming Styles
private const string _prefix = @"\\?\";
private const string _uncPrefix = _prefix + @"UNC\";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WIN32_FIND_DATA
{
public FileAttributes fileAttributes;
public uint ftCreationTimeLow;
public uint ftCreationTimeHigh;
public uint ftLastAccessTimeLow;
public uint ftLastAccessTimeHigh;
public uint ftLastWriteTimeLow;
public uint ftLastWriteTimeHigh;
public uint fileSizeHigh;
public uint fileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
}
[标志]
公共枚举目录EnumerateOptions
{
无=0x0,
递归=0x1,
TrowerRors=0x2,//如果你真的想要的话
ExpandEnvironmentVariables=0x4,
}
公共静态类实用程序
{
公共静态IEnumerable EnumerateFileSystem(字符串directoryPath,DirectoryEnumerateOptions=DirectoryEnumerateOptions.None)
{
if(directoryPath==null)
抛出新ArgumentNullException(nameof(directoryPath));
如果(!Path.IsPathRooted(directoryPath))
{
directoryPath=Path.GetFullPath(directoryPath);
}
返回EnumerateFileSystemRespivate(目录路径,选项);
}
私有静态IEnumerable EnumerateFileSystemeSprivate(字符串directoryPath,DirectoryEnumerateOptions=DirectoryEnumerateOptions.None)
{
如果(!Directory.Exists(directoryPath))
屈服断裂;
var findPath=Normalize(directoryPath,options.hasvag(DirectoryEnumerateOptions.ExpandEnvironmentVariables));
如果(!findPath.EndsWith(“*”))
{
findPath=Path.Combine(findPath,“*”);
}
var h=FindFirstFile(findPath,输出var数据);
if(h==无效的\u句柄\u值)
{
if(options.HasFlag(DirectoryEnumerateOptions.throwers))
抛出新的Win32Exception(Marshal.GetLastWin32Error());
屈服断裂;
}
如果(包括(参考数据))
{
返回信息(参考数据,目录路径);
if(options.HasFlag(DirectoryEnumerateOptions.Recursive)和&data.fileAttributes.HasFlag(fileAttributes.Directory))
{
foreach(EnumerateFileSystemEnterpriseSprivate(Path.Combine(directoryPath,data.cFileName),options)中的var wfd)
{
产量回报率;
}
}
}
做
{
如果(!FindNextFile(h,out数据))
{
if(Marshal.GetLastWin32Error()==错误\u无\u更多\u文件)
{
FindClose(h);
打破
}
继续;
}
如果(包括(参考数据))
{
返回信息(参考数据,目录路径);
if(options.HasFlag(DirectoryEnumerateOptions.Recursive)和&data.fileAttributes.HasFlag(fileAttributes.Directory))
{
foreach(EnumerateFileSystemEnterpriseSprivate(Path.Combine(directoryPath,data.cFileName),options)中的var wfd)
{
产量回报率;
}
}
}
}
虽然(正确);
}
私有静态bool包括(ref WIN32_FIND_DATA DATA)=>DATA.cFileName!=“&&DATA.cFileName!=”;
私有静态文件系统信息ToInfo(参考WIN32\u FIND\u DATA,字符串directoryPath)
{
if(data.fileAttributes.HasFlag(fileAttributes.Directory))
返回新的FileInfo(Path.Combine(directoryPath,data.cFileName));
返回新的DirectoryInfo(Path.Combine(directoryPath,data.cFileName));
}
私有静态字符串规范化(字符串路径、bool expandEnvironmentVariables)
{
if(路径==null)
返回null;
字符串扩展;
if(expandEnvironmentVariables)
{
expanded=Environment.ExpandEnvironmentVariables(路径);
}
其他的
{
扩展=路径;
}
if(扩展的.StartsWith(_前缀))
回报扩大;
if(扩展的.StartsWith(@“\\”)
返回ncPrefix+扩展的子字符串(2);
返回_前缀+扩展;
}
[DllImport(“kernel32”,SetLastError=true,CharSet=CharSet.Unicode)]
私有静态外部IntPtr FindFirstFile(字符串lpFileName,out WIN32_FIND_DATA lpFindFileData);
[DllImport(“内核32”,SetLastError=true)]
私有静态外部bool FindClose(IntPtr hFindFile);
[DllImport(“kernel32”,SetLastError=true,CharSet=CharSet.Unicode)]
私有静态外部bool FindNextFile(IntPtr hFindFile,out WIN32_FIND_DATA lpFindFileData);
#pragma警告禁用IDE1006//命名样式
private const int ERROR\u NO\u MORE\u FILES=18;
私有静态只读IntPtr无效\u句柄\u值=新IntPtr(-1);
#pragma警告还原IDE1006//命名样式
私有常量字符串\u前缀=@“\\?\”;
private const string_uncPrefix=_prefix+@“UNC\”;
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
内部结构WIN32\u查找\u数据
{
公共文件属性文件属性;
公共uint ftCreationTimeLow;
公共大学
[Flags]
public enum DirectoryEnumerateOptions
{
None = 0x0,
Recursive = 0x1,
ThrowErrors = 0x2, // if you really want it
ExpandEnvironmentVariables = 0x4,
}
public static class Utilities
{
public static IEnumerable<FileSystemInfo> EnumerateFileSystemEntries(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (directoryPath == null)
throw new ArgumentNullException(nameof(directoryPath));
if (!Path.IsPathRooted(directoryPath))
{
directoryPath = Path.GetFullPath(directoryPath);
}
return EnumerateFileSystemEntriesPrivate(directoryPath, options);
}
private static IEnumerable<FileSystemInfo> EnumerateFileSystemEntriesPrivate(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (!Directory.Exists(directoryPath))
yield break;
var findPath = Normalize(directoryPath, options.HasFlag(DirectoryEnumerateOptions.ExpandEnvironmentVariables));
if (!findPath.EndsWith("*"))
{
findPath = Path.Combine(findPath, "*");
}
var h = FindFirstFile(findPath, out var data);
if (h == INVALID_HANDLE_VALUE)
{
if (options.HasFlag(DirectoryEnumerateOptions.ThrowErrors))
throw new Win32Exception(Marshal.GetLastWin32Error());
yield break;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
do
{
if (!FindNextFile(h, out data))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_FILES)
{
FindClose(h);
break;
}
continue;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
}
while (true);
}
private static bool Include(ref WIN32_FIND_DATA data) => data.cFileName != "." && data.cFileName != "..";
private static FileSystemInfo ToInfo(ref WIN32_FIND_DATA data, string directoryPath)
{
if (data.fileAttributes.HasFlag(FileAttributes.Directory))
return new FileInfo(Path.Combine(directoryPath, data.cFileName));
return new DirectoryInfo(Path.Combine(directoryPath, data.cFileName));
}
private static string Normalize(string path, bool expandEnvironmentVariables)
{
if (path == null)
return null;
string expanded;
if (expandEnvironmentVariables)
{
expanded = Environment.ExpandEnvironmentVariables(path);
}
else
{
expanded = path;
}
if (expanded.StartsWith(_prefix))
return expanded;
if (expanded.StartsWith(@"\\"))
return _uncPrefix + expanded.Substring(2);
return _prefix + expanded;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", SetLastError = true)]
private static extern bool FindClose(IntPtr hFindFile);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
#pragma warning disable IDE1006 // Naming Styles
private const int ERROR_NO_MORE_FILES = 18;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
#pragma warning restore IDE1006 // Naming Styles
private const string _prefix = @"\\?\";
private const string _uncPrefix = _prefix + @"UNC\";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WIN32_FIND_DATA
{
public FileAttributes fileAttributes;
public uint ftCreationTimeLow;
public uint ftCreationTimeHigh;
public uint ftLastAccessTimeLow;
public uint ftLastAccessTimeHigh;
public uint ftLastWriteTimeLow;
public uint ftLastWriteTimeHigh;
public uint fileSizeHigh;
public uint fileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
}