我是C#的新手。我有一个文本框,我输入要搜索的文件,然后搜索'按钮。在搜索时钟我希望它填充文件夹中的文件,但我得到上述错误。以下是我的代码:
string[] directories = Directory.GetDirectories(@"d:\",
"*",
SearchOption.AllDirectories);
string file = textBox1.Text;
DataGrid dg = new DataGrid();
{
var files = new List<string>();
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
{
try
{
files.AddRange(Directory.GetFiles(d.RootDirectory.FullName, file , SearchOption.AllDirectories));
}
catch(Exception ex)
{
MessageBox.Show("the exception is " + ex.ToString());
//Logger.Log(e.Message); // Log it and move on
}
}
请帮我解决。感谢
答案 0 :(得分:2)
最重要的规则是:
不使用
SearchOption.AllDirectories
!
使用SearchOption.TopDirectoryOnly
代替递归搜索,用于所有可访问的目录。
使用SearchOption.AllDirectories
,一次访问冲突将在处理任何文件/目录之前破坏整个循环。但是,如果您使用SearchOption.TopDirectoryOnly
,则只会跳过无法访问的内容。
每个子目录检查使用Directory.GetAccessControl()
有一种更困难的方法,看看你是否可以预先访问目录(这个选项相当困难 - 除非你真的推荐这个确切地知道访问系统是如何工作的。)
对于递归搜索,我将此代码实现为自己使用:
public static List<string> GetAllAccessibleDirectories(string path, string searchPattern) {
List<string> dirPathList = new List<string>();
try {
List<string> childDirPathList = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly).ToList(); //use TopDirectoryOnly
if (childDirPathList == null || childDirPathList.Count <= 0) //this directory has no child
return null;
foreach (string childDirPath in childDirPathList) { //foreach child directory, do recursive search
dirPathList.Add(childDirPath); //add the path
List<string> grandChildDirPath = GetAllAccessibleDirectories(childDirPath, searchPattern);
if (grandChildDirPath != null && grandChildDirPath.Count > 0) //this child directory has children and nothing has gone wrong
dirPathList.AddRange(grandChildDirPath.ToArray()); //add the grandchildren to the list
}
return dirPathList; //return the whole list found at this level
} catch {
return null; //something has gone wrong, return null
}
}
这就是你怎么称呼它
List<string> accessibleDirs = GetAllAccessibleDirectories(myrootpath, "*");
然后,您只需要在所有可访问目录中搜索/添加文件。
注意:这个问题非常经典。我相信还有一些其他更好的解决方案。
如果在获得所有可访问的目录后有一些特别想要避免的目录,您还可以使用目录的部分名称作为关键字来过滤LINQ的List
结果(即Recycle.Bins
)。
答案 1 :(得分:1)
正如Ian在他的post中指定的那样,请不要使用递归文件列表(Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)
),因为第一个异常将停止进一步处理。
此外,为了在某种程度上缓解此类问题并获得更好的结果,您应该将此程序作为Administrator
运行。这可以通过在Windows资源管理器中右键单击您的应用程序,然后选中Run this program as an administrator
选项卡上的Compatibility
选项来完成。
此外,您应该使用以下代码进行搜索,因此中间异常不会停止进一步搜索。
static void Main(string[] args) {
string fileToFind = "*.jpg";
var files = new List<string>();
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
files.AddRange(FindDirectory(fileToFind, d.RootDirectory.FullName));
}
/// <summary>
/// This function returns the full file path of the matches it finds.
/// 1. It does not do any parameter validation
/// 2. It searches recursively
/// 3. It eats up any error that occurs when requesting files and directories within the specified path
/// 4. Supports specifying wildcards in the fileToFind parameter.
/// </summary>
/// <param name="fileToFind">Name of the file to search, without the path</param>
/// <param name="path">The path under which the file needs to be searched</param>
/// <returns>Enumeration of all valid full file paths matching the file</returns>
public static IEnumerable<string> FindDirectory(string fileToFind, string path) {
// Check if "path" directly contains "fileToFind"
string[] files = null;
try {
files = Directory.GetFiles(path, fileToFind);
} catch { }
if (files != null) {
foreach (var file in files)
yield return file;
}
// Check all sub-directories of "path" to see if they contain "fileToFInd"
string[] subDirs = null;
try {
subDirs = Directory.GetDirectories(path);
} catch { }
if (subDirs == null)
yield break;
foreach (var subDir in subDirs)
foreach (var foundFile in FindDirectory(fileToFind, subDir))
yield return foundFile;
}