【问题标题】:Security Exception while use FileSystemObject in C#在 C# 中使用 FileSystemObject 时出现安全异常
【发布时间】:2016-04-16 08:10:44
【问题描述】:

我想写一个快速的磁盘使用检测程序,发现FileSystemObject是最快的方法。而FileSystemObjectCOM -> Microsoft Scripting Runtime 中。

所有代码都很简单,我这里解析一下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DiskUsage
{
    class Program
    {
        const string FolderPath = @"C:\Windows\System32";

        static void Main(string[] args)
        {
            var startTime = DateTime.Now;

            Scripting.FileSystemObject fso = new Scripting.FileSystemObject();
            Scripting.Folder folder = fso.GetFolder(FolderPath);
            Int64 dirSize = (Int64)folder.Size;

            TimeSpan span = DateTime.Now.Subtract(startTime);

            System.Console.WriteLine("{1} size: {0}", dirSize, FolderPath);
            System.Console.WriteLine("use time: {0}", span);
            System.Console.ReadKey();
        }
    }
}

我将app.manifest 设置为

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

当我测试我的程序时,安全异常出现在这一行

Int64 dirSize = (Int64)folder.Size;

异常信息(我手动翻译,对不起我的英语不好。)是

Unhandled exception type “System.Security.SecurityException” occurred in DiskUsage.exe 
Other message: exception from HRESULT:0x800A0046 (CTL_E_PERMISSIONDENIED)

如果我将FolderPath 更改为@"D:\Codes"。它工作正常。所以我认为清单中的安全设置对COM -&gt; Microsoft Scripting Runtime 没有影响。有人知道怎么修这个东西吗?请帮忙,谢谢。

【问题讨论】:

    标签: c# security com uac filesystemobject


    【解决方案1】:

    当调用 Size 属性时,神奇的事情发生了。在内部,它仍然遍历完整的文件夹树和确定文件夹大小的文件。如果您当前的身份(无论是否提升)无权列出任何子文件夹中的文件,那么您不走运,对Size 的调用将失败。

    我使用 System.IO 中的 Directory 类重新实现了文件夹遍历,但添加了一些日志记录和异常处理,因此它会告诉您文件夹的大小,至少对于您可以访问的文件而言.

    您的 main 方法需要进行此更改:

    Int64 dirSize;
    try { 
        dirSize = (Int64)folder.Size;
    }
    catch(SecurityException sec)
    {
        dirSize = FolderSize(FolderPath);
    }
    

    如果您遇到异常,我们会调用 FolderSize 的 c# 实现,但这一次它将补偿未经授权的异常。

    static Int64 FolderSize(string path)
    {
        long sum =0;
        try
        {
            // scan folders
            foreach(var dir in Directory.EnumerateDirectories(path))
            {
                //recursive call
                sum += FolderSize( dir);
            }
        } 
        catch(UnauthorizedAccessException unath)
        {
            Console.WriteLine("{0} for folder {1}", unath.Message, path);
        }
        try
        {
            // scan files
            foreach (var file in Directory.EnumerateFiles(path))
            {
                sum += new FileInfo(file).Length;
            }
        }
        catch(UnauthorizedAccessException filesec)
        {
            Console.WriteLine("{0} for file {1}", filesec.Message, path);
        }
        return sum;
    }
    

    【讨论】:

    • 感谢您的回答。它会起作用,但我认为核心问题是如何获得访问所有文件的权限?
    • 您不能保证对所有文件的权限@Jennal 您可能会提升您的进程和/或找到缺少权限的文件夹,尝试获取它们的所有权,分配权限等,但那不是万无一失。我的解决方案为您提供了您有权访问的文件的文件夹大小。
    猜你喜欢
    • 1970-01-01
    • 2011-04-01
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    相关资源
    最近更新 更多