【问题标题】:Access to the path 'C:\ProgramData\Application Data' is denied拒绝访问路径“C:\ProgramData\Application Data”
【发布时间】:2017-04-20 09:21:22
【问题描述】:

我希望得到文件夹的大小

C:\ProgramData\

我使用下面的代码

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

但它提示我错误:

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

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

我已经设置好了

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

在 app.manifest 中。似乎即使我直接在 Windows 中打开 C:\ProgramData\Application Data 它也被拒绝了。

如何解决这个问题?

【问题讨论】:

  • 那条路径是一个系统连接点,对你来说并不是真的有用。您应该使用%AppData% 代替C:\Users\&lt;you&gt;\AppData\Roaming 作为路径。或者将%LocalAppData% 用于C:\Users\&lt;you&gt;\AppData\Local。也可以使用%UserProfile%\AppData获取C:\Users\&lt;you&gt;\AppData
  • 您的管理员用户是否拥有“完全控制”权限?
  • 您是否尝试过使其成为完全信任的应用程序? (项目的)属性-> 安全性-> 启用单击一次安全性-> 选择完全信任应用程序
  • 你能进入bin文件夹然后以管理员身份打开吗?这不是解决方案,但有助于定位问题。您可以使用msdn.microsoft.com/en-us/library/… 发出某种警告
  • @Heki %ProgramData% != %AppData%

标签: c#


【解决方案1】:

我想你不能这样做,来自下面的命令:

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]

您可以看到,Application Data 是一个连接点,它指向 ProgramData。 Windows 包含许多类似的连接点,用于向后兼容旧应用程序。

连接点上的安全权限明确禁止列出文件,这就是为什么您无法获取其内容列表的原因:

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

更多信息来自:What is the Programdata/Application Data folder?

【讨论】:

  • 如何防止使用 DirectoryInfo.EnumerateFiles 扫描联结文件夹,或者有更好的方法来获取 ProgramData 文件夹的大小(不包括联结文件夹)
  • DirectoryInfo 有一个Property Attributes,所以你可以使用Attributes 来过滤你需要计算哪种DirectoryInfo。例如,您可以使用它来过滤不是 ReparsePoint 的目录: (di.Attributes & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint
【解决方案2】:

由于某些原因,在文件系统上枚举可能会引发SecurityException

最好的选择是对这些异常进行回调。

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;
    }
}

最后

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;
    } );

【讨论】:

    猜你喜欢
    • 2011-03-29
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多