目录获取目录的问题访问被拒绝的异常和长路径

时间:2014-09-26 16:25:44

标签: c# winforms

我有以下代码,它找到并显示空文件夹,遗憾的是它无法处理所有文件夹,回收站和应用程序数据文件夹导致访问异常。

再往下是来自另一个使用枚举的用户的示例,有了它我可以访问受限制的文件夹,但它无法处理长路径。

我正在尝试Delimon.Win32.IO;来自http://gallery.technet.microsoft.com/scriptcenter/DelimonWin32IO-Library-V40-7ff6b16c的命名空间它显然可以处理长路径(我还没有测试过它)

我需要一个可以处理访问限制和长路径的解决方案 - 如果可能的话。

private void button1_Click(object sender, EventArgs e)
    {
        //Open folder browser for user to select the folder to scan
        DialogResult result = folderBrowserDialog1.ShowDialog();
        if (result == DialogResult.OK)
        {
            //Clear text fields
            listBoxResults.Items.Clear();
            listBoxPath.Items.Clear();
            txtFoldersFound.Clear();

            //Store selected folder path
            string dirPath = folderBrowserDialog1.SelectedPath;

            //Process the folder
            try
            {
                foreach (string dir in Directory.GetDirectories(dirPath, "*.*", SearchOption.AllDirectories))
                {
                    //Populate List Box with all folders found
                    this.Invoke(new Action(() => listUpdate2(dir)));
                    if (Directory.GetDirectories(dir).Length.Equals(0))
                    {
                        //Populate List Box with all empty folders found
                        this.Invoke(new Action(() => listUpdate1(dir + Environment.NewLine)));
                    }
                }
                //Count of the empty folders
                txtFoldersFound.Text = listBoxResults.Items.Count.ToString();
            }
            //Catch exceptions, seems to be folders not accessible causing this. Recycle Bin, App Data etc
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

似乎枚举目录仍然是.NET 4.5中的一个问题:

https://connect.microsoft.com/VisualStudio/feedback/details/512171/directory-enumeratedirectory-etc-unusable-due-to-frequent-unauthorizedaccessexceptions-even-runas-administrator

提供的代码使用递归来遍历目录结构。

private void button1_Click(object sender, EventArgs e)
    {
        //Open folder browser for user to select the folder to scan
        DialogResult result = folderBrowserDialog1.ShowDialog();
        if (result == DialogResult.OK)
        {
            //Clear text fields
            listBoxResults.Items.Clear();
            listBoxPath.Items.Clear();
            txtFoldersFound.Clear();

            //Store selected folder path
            string dirPath = folderBrowserDialog1.SelectedPath;

            Action<string> performOnEachFolder = (s) => this.Invoke(new Action(() => listUpdate2(s)));
            foreach (string emptyFolder in GetAllEmptyFolders(dirPath, performOnEachFolder))
                this.Invoke(new Action(() => listUpdate2(emptyFolder)));

        }
    }

    private static IEnumerable<string> GetAllEmptyFolders(string path, Action<string> performOnEachFolder)
    {

        performOnEachFolder(path);

        EmptyResult result = IsDirectoryEmpty(path);

        if (result == EmptyResult.Empty)
            yield return path;

        if (result == EmptyResult.Error)
            yield break;

        //A reparse point may indicate a recursive file structure. Cause this to stop the recursion. 
        //http://blogs.msdn.com/b/oldnewthing/archive/2004/12/27/332704.aspx
        if ((File.GetAttributes(path) & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
            yield break;

        IEnumerator<string> it = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly).GetEnumerator();

        while (it.MoveNext())
        {
            foreach (string emptyFolder in GetAllEmptyFolders(it.Current, performOnEachFolder))
            {
                yield return emptyFolder;
            }
        }
    }

    private enum EmptyResult
    {
        Empty = 1,
        Used = 2,
        Error = 3
    }

    private static EmptyResult IsDirectoryEmpty(string path)
    {
        try
        {
            return !Directory.EnumerateFileSystemEntries(path).Any() ? EmptyResult.Empty : EmptyResult.Used;
        }
        catch (UnauthorizedAccessException)
        {
            //We do not want the method to throw as that will cause problems with the iterator block.
            return EmptyResult.Error;
        }
    }