我正在运行下面的代码并在下面获得例外。我是否被迫将此函数放入try catch中,还是以其他方式递归获取所有目录? 我可以编写自己的递归函数来获取文件和目录。但我想知道是否有更好的方法。
// get all files in folder and sub-folders
var d = Directory.GetFiles(@"C:\", "*", SearchOption.AllDirectories);
// get all sub-directories
var dirs = Directory.GetDirectories(@"C:\", "*", SearchOption.AllDirectories);
“拒绝访问路径'C:\ Documents and Settings \'。”
答案 0 :(得分:34)
如果你想在失败后继续使用下一个文件夹,那么是的;你必须自己做。我建议Stack<T>
(深度优先)或Queue<T>
(bredth优先)而不是递归,以及迭代器块(yield return
);那么你可以避免堆栈溢出和内存使用问题。
示例:
public static IEnumerable<string> GetFiles(string root, string searchPattern)
{
Stack<string> pending = new Stack<string>();
pending.Push(root);
while (pending.Count != 0)
{
var path = pending.Pop();
string[] next = null;
try
{
next = Directory.GetFiles(path, searchPattern);
}
catch { }
if(next != null && next.Length != 0)
foreach (var file in next) yield return file;
try
{
next = Directory.GetDirectories(path);
foreach (var subdir in next) pending.Push(subdir);
}
catch { }
}
}
答案 1 :(得分:9)
您可以设置程序,以便只能以管理员身份运行。
在 Visual Studio :
中Right click on the Project -> Properties -> Security -> Enable ClickOnce Security Settings
单击它后,将在Project的属性文件夹 app.manifest 下创建一个文件,一旦创建该文件,您可以取消选中Enable ClickOnce Security Settings
选项
打开该文件并更改此行:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
为:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
这将使程序需要管理员权限,并且它将保证您有权访问该文件夹。
答案 2 :(得分:2)
好吧,你要么避开你没有权限的目录,要么你没有权限,但是当访问被拒绝时,你可以优雅地回复。
如果选择第一个选项,则需要确保知道它们是哪个目录,以及线程标识的权限不会更改。这很棘手,容易出错;我不推荐它用于生产质量的系统。
第二种选择看起来更合适。使用try / catch块并跳过任何“禁止”目录。
答案 3 :(得分:0)
我知道这个问题有些陈旧,但今天我遇到了同样的问题,我发现以下文章详细解释了“文件夹递归”解决方案。
文章承认GetDirectories()
方法的缺陷......:
不幸的是,[[strong> 使用GetDirectories()方法 ]存在问题。其中的关键是一些 您尝试读取的文件夹可以配置为 当前用户可能无法访问它们。而不是忽略文件夹 你有限制访问权限,该方法抛出一个 UnauthorizedAccessException。但是,我们可以绕过这个问题 通过创建我们自己的递归文件夹搜索代码。
...然后详细介绍解决方案:
答案 4 :(得分:0)
已经指出你需要自己做,所以我想我会分享我的解决方案,避免收集。应该注意的是,这将忽略所有错误,而不仅仅是AccessDenied。要改变它,你可以使catch块更具体。
IEnumerable<string> GetFiles(string folder, string filter, bool recursive)
{
string [] found = null;
try
{
found = Directory.GetFiles(folder, filter);
}
catch { }
if (found!=null)
foreach (var x in found)
yield return x;
if (recursive)
{
found = null;
try
{
found = Directory.GetDirectories(folder);
}
catch { }
if (found != null)
foreach (var x in found)
foreach (var y in GetFiles(x, filter, recursive))
yield return y;
}
}
答案 5 :(得分:0)
此递归方法将返回该文件夹中所有可访问文件的列表。
static List<string> getFilesInDir(string dirPath)
{
List<string> retVal = new List<string>();
try
{
retVal = IO.Directory.GetFiles(dirPath, "*.*", IO.SearchOption.TopDirectoryOnly).ToList();
foreach (IO.DirectoryInfo d in new IO.DirectoryInfo(dirPath).GetDirectories("*", IO.SearchOption.TopDirectoryOnly))
{
retVal.AddRange(getFilesInDir(d.FullName));
}
}
catch (Exception ex)
{
//Console.WriteLine(dirPath);
}
return retVal;
}
答案 6 :(得分:0)
您可以通过对第三个参数使用EnumerationOptions
来实现此目的。此类提供了一个名为IgnoreInaccessible
的属性,该属性可在遇到无法访问的文件/文件夹时切换是否引发异常。
与搜索有关的其他属性也可用,请参见:EnumerationOptions Class (System.IO)
示例:
var options = new EnumerationOptions()
{
IgnoreInaccessible = true
};
var files = Directory.GetFiles("mypath", "*.*", options);
foreach (var file in files)
{
// File related activities
}
注意::IgnoreAccessible
默认情况下设置为true,但出于可见性考虑,我在上面的示例中将其包括在内。
答案 7 :(得分:-1)
战斗代码示例。不要注意特殊类型。
private void RecursiveDirProcessing(DirectoryInfo dirInfoRoot, ref Dictionary<OfficeType, List<FileInfo>> dict)
{
try
{
// DO IT! Using dict, we will return the lists
}
catch
{
AddLog(TypeLog.Error, $"Нет доступа к каталогу {dirInfoRoot.FullName}");
return;
}
foreach (DirectoryInfo dirInfoDirectory in dirInfoRoot.GetDirectories("*", SearchOption.TopDirectoryOnly))
{
RecursiveDirProcessing(dirInfoDirectory, ref dict);
}
}
RecursiveDirProcessing(dirInfoObj, ref dict);