简体   繁体   中英

How to access files inside "System Volume Information" Directory

I'm trying to get list of all files inside a folder (or drive).

Directory.GetFiles("C:\\", "*.*", SearchOption.AllDirectories)

throws an error because access to some directories like System Volume Information is denied. all answer about this are suggesting catching the error and bypassing these directories while my main purpose is bypassing other directories and read these special directories.

I know that I can grant access and then revoke the access like:

icacls "C:\System Volume Information" /grant username:F

and

icacls "C:\system volume information" /remove username

but it does not seem like a wise choice just to run 2 process (one for granting and one for revoking) access to each directory with System.UnauthorizedAccessException .

is there a better way to grant access to such directories programmatically?

I don't think it's a good idea to grant access to users for system folders in general. Your approach is to search for any folder under C:. This creates all kind of problems, since MS creates folders there with only SYSTEM access. If you really want access to everything, I would suggest that you run your app as SYSTEM. Otherwise, filter out the folders you really need access to, and only try to access them. There is multiple solutions out there on how to run your program as the SYSTEM user. One of them (which I casually use when testing) is PSTools.

https://docs.microsoft.com/en-us/sysinternals/downloads/pstools

As mention grant access to folder is even temporarily not a good idea. But if you really need that temporarily access only for enumeration files you can modify ACL to grant current user right to read folder only (Enumerate file) and restore it back after enumeration in C# without call additional utilities.

Code above above can do such enumeration that way. Beware ever admin account in some folder don't have access to modify or read ACL.

public static IReadOnlyList<string> EnumerateFile(
        string path,
        bool recursive = false,
        bool ignoreError = true)
    {
        var currentIdentity = WindowsIdentity.GetCurrent();
        List<string> result;

        try
        {
            result = Directory.EnumerateFiles(path).ToList();

            if (recursive)
            {
                foreach(var dir in Directory.EnumerateDirectories(path))
                {
                    var r = EnumerateFile(dir, true);
                    result.AddRange(r);
                }
            }

            return result;
        }
        catch(UnauthorizedAccessException)
        {
            try
            {
                var accessControl = Directory.GetAccessControl(path);

                accessControl.ModifyAccessRule(
                    AccessControlModification.Add,
                    new FileSystemAccessRule(
                        currentIdentity.User,
                        FileSystemRights.ListDirectory,
                        AccessControlType.Allow),
                    out var success);

                if (!success)
                    throw new UnauthorizedAccessException();

                Directory.SetAccessControl(path, accessControl);

                result = Directory.EnumerateFiles(path).ToList();
                if (recursive)
                {
                    foreach (var dir in Directory.EnumerateDirectories(path))
                    {
                        var r = EnumerateFile(dir, true);
                        result.AddRange(r);
                    }
                }

                accessControl.ModifyAccessRule(
                    AccessControlModification.Remove,
                    new FileSystemAccessRule(
                        currentIdentity.User,
                        FileSystemRights.ListDirectory,
                        AccessControlType.Allow),
                    out _);

                Directory.SetAccessControl(path, accessControl);

                return result;
            }
            catch (UnauthorizedAccessException e)
            {
                return ignoreError ? new List<string>() : throw e;
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM