5

更新:我很高兴放弃 C# 要求,只看到任何可以列出所有以管理员或系统身份运行的文件的程序,我的问题是有人见过这样的事情吗?

枚举目录中的文件有多种方法,但都遇到相同的问题:

“指定的路径、文件名或两者都太长。完全限定文件名必须小于 260 个字符,目录名必须小于 248 个字符。”

“访问路径 'C:\Users\All Users\Application Data' 被拒绝”

等等

即使在管理员、单用户机器下运行,似乎也无法在不遇到异常\错误的情况下列出所有文件。

仅仅获取windows下所有文件的列表真的是一项不可能完成的任务吗?有没有人能够使用 C# 或任何其他方法获得他们机器上所有文件的完整列表?

这个来自 MS的链接,标题为“枚举目录和文件”,没有显示如何枚举目录和文件,它只显示了不会抛出的内容的一个子集:DirectoryNotFoundException、UnauthorizedAccessException、PathTooLongException、

更新:这是在 C 上运行并尝试枚举所有文件和错误的示例代码。即使以管理员身份运行它,也有一些文件夹不仅可以访问,而且我什至无法将其所有权更改为管理员!例如:“C:\Windows\CSC”

只需查看“错误 {0}.csv”日志文件,即可了解管理员无法访问的位置。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;


class Program
{

static System.IO.StreamWriter logfile;
static System.IO.StreamWriter errorfile;
static void Main(string[] args)
{
    string directory = @"C:\";

    logfile = new System.IO.StreamWriter(string.Format(@"E:\Files {0}.csv", DateTime.Now.ToString("yyyyMMddHHmm")));
    errorfile = new System.IO.StreamWriter(string.Format(@"E:\Errors {0}.csv", DateTime.Now.ToString("yyyyMMddHHmm")));
    TraverseTree(directory, OnGotFileInfo, OnGotException);

    logfile.Close();
    errorfile.Close(); 
}

public static void OnGotFileInfo(System.IO.FileInfo fileInfo)
{
    logfile.WriteLine("{0},{1},", fileInfo.FullName, fileInfo.Length.ToString("N0"));
}

public static void OnGotException(Exception ex, string info)
{
    errorfile.WriteLine("{0},{1}", ex.Message, info);
}

public static void TraverseTree(string root, Action<System.IO.FileInfo> fileAction, Action<Exception, string> errorAction)
{
    // Data structure to hold names of subfolders to be 
    // examined for files.
    Stack<string> dirs = new Stack<string>(20);

    if (!System.IO.Directory.Exists(root))
    {
        throw new ArgumentException();
    }
    dirs.Push(root);

    while (dirs.Count > 0)
    {
        string currentDir = dirs.Pop();
        string[] subDirs;
        try
        {
            subDirs = System.IO.Directory.GetDirectories(currentDir);
        }
        // An UnauthorizedAccessException exception will be thrown if we do not have 
        // discovery permission on a folder or file. It may or may not be acceptable  
        // to ignore the exception and continue enumerating the remaining files and  
        // folders. It is also possible (but unlikely) that a DirectoryNotFound exception  
        // will be raised. This will happen if currentDir has been deleted by 
        // another application or thread after our call to Directory.Exists. The  
        // choice of which exceptions to catch depends entirely on the specific task  
        // you are intending to perform and also on how much you know with certainty  
        // about the systems on which this code will run. 

        catch (System.Exception e)
        {
            errorAction(e, currentDir);
            continue;
        }

        string[] files = null;
        try
        {
            files = System.IO.Directory.GetFiles(currentDir);
        }

        catch (System.Exception e)
        {
            errorAction(e, currentDir);
            continue;
        }

        // Perform the required action on each file here. 
        // Modify this block to perform your required task. 
        foreach (string file in files)
        {
            try
            {
                // Perform whatever action is required in your scenario.
                System.IO.FileInfo fi = new System.IO.FileInfo(file);
                fileAction(fi);
            }
            catch (System.Exception e)
            {
                // If file was deleted by a separate application 
                //  or thread since the call to TraverseTree() 
                // then just continue.
                errorAction(e ,file);
                continue;
            }
        }

        // Push the subdirectories onto the stack for traversal. 
        // This could also be done before handing the files. 
        foreach (string str in subDirs)
            dirs.Push(str);
    }

    }
}
4

1 回答 1

6

是的,至少很难毫无例外地枚举所有文件。

这里有几个问题:

  • CLR 不支持某些路径(长路径 - PathTooLongException)
  • 文件夹/文件的安全限制
  • 引入重复的连接/硬链接(理论上循环以在递归迭代中使用 StackOverflow)。
  • 基本的共享违规限制(如果您尝试读取文件)。

对于 PathTooLongException:我认为您需要处理相应 Win32 函数的 PInvoke。CLR 中所有与路径相关的方法都限制为 256 个字符。

安全限制 - 如果您在系统下运行(不确定)或具有备份权限,您可能能够枚举所有内容,但任何其他帐户都保证无法访问默认配置的系统上的所有文件。您可以 PInvoke 本机版本并处理错误代码,而不是获取异常。您可以通过直接首先检查 ACL 来减少进入目录的异常数量。

于 2012-12-14T21:22:21.860 回答