2

I wish to get the size of folder

C:\ProgramData\

I use the following code

 public static long GetDirectorySize(string folderPath)
        {
            DirectoryInfo di = new DirectoryInfo(folderPath);
            return di.EnumerateFiles("*", SearchOption.AllDirectories).Sum(fi => fi.Length);
        }

But it prompts me error:

An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll

Additional information: Access to the path 'C:\ProgramData\Application Data' is denied.

I have already set the

<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

in app.manifest. It seems that even I open C:\ProgramData\Application Data in windows directly it is denied.

How to resolve this problem?

william007
  • 17,375
  • 25
  • 118
  • 194
  • 3
    That path is a system junction point and is not really useful to you anyway. You should use `%AppData%` for `C:\Users\\AppData\Roaming` as path instead. Alternatively use `%LocalAppData%` for `C:\Users\\AppData\Local`. You can also use `%UserProfile%\AppData` to get `C:\Users\\AppData` – Heki Apr 20 '17 at 09:25
  • 1
    Does your administrator user have "Full Control" permission? – Samvel Petrosov Apr 20 '17 at 09:25
  • Have you tried making it a full trust application? Properties (of project) -> Security -> Enable Click Once Security -> Select Full trust application – EpicKip Apr 20 '17 at 09:26
  • Can you enter bin folder and than open it as administrator? It is not a solution, but would help locate the problem. You can make some kind alert by using https://msdn.microsoft.com/en-us/library/system.unauthorizedaccessexception(v=vs.110).aspx – Arkadiusz Raszeja Apr 20 '17 at 09:27
  • @Heki `%ProgramData%` != `%AppData%` – Sir Rufo Apr 20 '17 at 10:00
  • @SirRufo I am not claiming otherwise. I understand why you say it though cause arguably it is an irrelevant comment in that regard. However, usually any application that will be installed, which is written in C#, is a click-once app - so I made that assumption. – Heki Apr 20 '17 at 11:52
  • was running this program from command prompt initially , now running the command prompt in Administrator mode and ran the program. This helped me in get rid of this error. – Venkataramana Madugula Oct 23 '20 at 12:45

2 Answers2

0

I suppose you cannot do so, from command bellow:

C:\ProgramData>dir /a
Volume in drive C is OSDisk
Volume Serial Number is 067E-828E

Directory of C:\ProgramData

04/20/2017  02:00 PM    <DIR>          .
04/20/2017  02:00 PM    <DIR>          ..
07/14/2009  01:08 PM    <JUNCTION>     Application Data [C:\ProgramData]

You can see, Application Data is a junction point which points back to ProgramData. Windows includes a number of similar junction points, for backwards compatibility with older applications.

The security permissions on the junction point explicitly prohibit listing files, which is why you can't get a listing of its contents:

C:\ProgramData>icacls "Application Data" /L
Application Data Everyone:(DENY)(S,RD)
                 Everyone:(RX)
                 NT AUTHORITY\SYSTEM:(F)
                 BUILTIN\Administrators:(F)

See more info from: What is the Programdata/Application Data folder?

Community
  • 1
  • 1
Justin Shi
  • 304
  • 2
  • 6
  • How do I prevent scanning of junction folder using DirectoryInfo.EnumerateFiles, or there are better methods to get the size of ProgramData folder (excluding junction folder) – william007 Apr 20 '17 at 09:41
  • DirectoryInfo has a Property Attributes, so you can use Attributes to filter which kind of DirectoryInfo you need to calculate. For example, you can use this to filter the Directory which is not ReparsePoint: (di.Attributes & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint – Justin Shi Apr 20 '17 at 10:07
0

Enumerating on the file system can raise SecurityException for some reasons.

Best option is to have a callback for those Exceptions.

public class FileSytemInfoErrorArgs
{
    public FileSytemInfoErrorArgs( FileSystemInfo fileSystemInfo, Exception error )
    {
        FileSystemInfo = fileSystemInfo;
        Error = error;
    }

    public FileSystemInfo FileSystemInfo { get; }
    public Exception Error { get; }
    public bool Handled { get; set; }
}

public static class DirectoryInfoExtensions
{
    public static long GetTotalSize( this DirectoryInfo di, Action<FileSytemInfoErrorArgs> errorAction = null )
    {
        long size = 0;

        foreach ( var item in di.EnumerateFileSystemInfos() )
        {
            try
            {
                size += ( item as FileInfo )?.Length
                    ?? ( item as DirectoryInfo )?.GetTotalSize( errorAction )
                    ?? throw new InvalidOperationException();
            }
            catch ( Exception ex )
            {
                var arg = new FileSytemInfoErrorArgs( item, ex );
                errorAction?.Invoke( arg );
                if ( !arg.Handled )
                {
                    throw;
                }
            }
        }

        return size;
    }
}

and finally

var path = Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData );
var dir = new DirectoryInfo( path );
var totalSize = dir.GetTotalSize(
    errorAction: e =>
    {
        // Console.WriteLine( "{0}: {1}", e.FileSystemInfo.FullName, e.Error.Message );
        e.Handled = true;
    } );
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73