0

我想在放置在我的表单中的列表视图中显示文件夹和文件大小。

是否可以整体实现文件夹大小(包括子文件夹和文件)并从远程计算机显示?

使用以下代码,我可以获得原始文件大小,但并非全部获得原始文件夹大小。取而代之的是,am getting folder size as 0kb

ManagementScope ManagementScope1 = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", strIP), options);
ManagementScope1.Connect();
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ObjectQuery obq1 = new ObjectQuery("Associators of {Win32_Directory.Name='D:'} Where ResultRole = PartComponent ");
ManagementObjectSearcher searcher1 = new ManagementObjectSearcher(ManagementScope1, obq1);

foreach (ManagementObject ManagementObject2 in searcher1.Get())
{
    lvData[0] = ManagementObject2["FileName"].ToString();
    lvData[1] = formatSize(Convert.ToInt64(ManagementObject2["FileSize"]));
    ListViewItem lvItem = new ListViewItem(lvData, 0);
    lvFiles.Items.Add(lvItem);
}

formatSize() 如下:

protected string formatSize(Int64 lSize)
{
        //Format number to KB
     string stringSize = "";
     NumberFormatInfo myNfi = new NumberFormatInfo();

     Int64 lKBSize = 0;

     if (lSize < 1024)
     {
         if (lSize == 0)
         {
            //zero byte
            stringSize = "0";
         }
         else
         {
            //less than 1K but not zero byte
            stringSize = "1";
         }
      }
      else
      {
            //convert to KB
            lKBSize = lSize / 1024;
            //format number with default format
            stringSize = lKBSize.ToString("n", myNfi);
            //remove decimal
            stringSize = stringSize.Replace(".00", "");
      }
      return stringSize + " KB";
 }

我也尝试了这个链接,但是我失败了,因为当我使用对象引用时没有将对象引用设置为对象 错误的实例,

FolderSize += (UInt64)ManagementObject2["FileSize"]; 
lvData[1] = formatSize(Convert.ToInt64 (FolderSize));

好心的人帮助我克服这个问题。

4

2 回答 2

2

正如@rene 指出的那样,问题在于文件夹实际上没有大小。它们是容器。要获得总大小,您必须枚举目录和子目录中的所有文件来计算它。

摘自MSDN

文件大小

数据类型: uint64

访问类型:只读

文件系统对象的大小,以字节为单位。尽管文件夹具有 FileSize 属性,但始终返回值 0。要确定文件夹的大小,请使用 FileSystemObject 或将文件夹中存储的所有文件的大小相加。有关在脚本中使用 uint64 值的更多信息,请参阅 WMI 中的脚本。

可以说,最简单的方法是使用DirectoryInfo类、UNC 路径和一些 LINQ。

var folder = @"\\MachineOrIp\c$\Temp";

        var directory = new DirectoryInfo(folder);
        var totalSize = directory.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length);

        Console.WriteLine("{0} - {1} Bytes", folder, totalSize);

这将允许您获得顶级文件夹的“总大小”(以字节为单位)。

于 2014-08-25T14:10:16.470 回答
2

文件夹没有大小,文件夹只是文件的容器,文件的大小决定了文件夹大小。

要获得总体文件夹大小,您可以通过找到磁盘大小和可用空间然后减去这两个来得出文件夹大小的近似值。

在后台使用CIM_DirectoryCIM_DataFile扫描文件夹。您可以使用管理范围和驱动器号 (D:) 调用扫描方法

我确实从一个 ThreadPool 线程中运行它,如下所示:

ManagementScope ManagementScope1 = new ManagementScope();
ManagementScope1.Connect();
ThreadPool.QueueUserWorkItem((que) => { scan(ManagementScope1, "D:"); });

使用 WMI 遍历文件夹

private void scan(ManagementScope scope, string drive)
{
var disk = scope.Device(drive).GetEnumerator();
if (!disk.MoveNext())
{
    Add(String.Format("{0} drive not found",drive),0);
    return;
}

Add(drive, disk.Current.Size() - disk.Current.FreeSpace());

// iterate over root Folders
foreach (var folder in scope.Folder(drive))
{
    ulong totalsize = 0;
    try
    {
        // iterate over the files
        foreach (var file in scope.File(
                    drive,
                    folder.Path(),
                    folder.FileName()))
        {
            totalsize += file.FileSize();
        }
        // iterate over all subfolders
        foreach (var subfolder in scope.SubFolder(drive
                    , folder.Path()
                    , folder.FileName()))
        {
            // iterate over files within a folder
            foreach (var file in scope.File(
                    drive,
                    subfolder.Path(),
                    subfolder.FileName()))
            {
                totalsize += file.FileSize();
            }
        }
    }
    catch (Exception exp)
    {
        Debug.WriteLine(exp.Message);
    }
    Add(folder.Name(), totalsize);  
}
}

扩展方法

原始代码变得接近不可维护,因此我实现了 ManagementScope 和 ManagementBaseObject 的扩展方法。

public static class ManagementObjectExtensions
{
    const string WQL_DEVICE = "Select Size,FreeSpace from Win32_LogicalDisk where Deviceid='{0}'";
    const string WQL_FOLDER = "Select Path, Filename, Name from CIM_Directory where Drive='{0}' and path='\\\\' and system = false and hidden = false and readable = true";
    const string WQL_SUBFOLDER = "Select Path, Filename from CIM_Directory where Drive='{0}' and path like '{1}{2}\\\\%' and system = false and hidden = false and readable = true";
    const string WQL_FILE = "Select FileSize from CIM_DataFile where Drive='{0}' AND Path = '{1}{2}\\\\' ";

    // internal helper to get an enumerable collection from any WQL
    private static ManagementObjectCollection GetWqlEnumerator(this ManagementScope scope, string wql, params object[] args)
    {
        return new ManagementObjectSearcher(
            scope,
            new ObjectQuery(
                String.Format(wql, args)))
            .Get();
    }

    public static ManagementObjectCollection Device(this ManagementScope scope, params object[] args)
    {
        return scope.GetWqlEnumerator(WQL_DEVICE, args);
    }

    public static ManagementObjectCollection Folder(this ManagementScope scope, params object[] args)
    {
        return scope.GetWqlEnumerator(WQL_FOLDER, args);
    }

    public static ManagementObjectCollection SubFolder(this ManagementScope scope, params object[] args)
    {
        return scope.GetWqlEnumerator(WQL_SUBFOLDER, args);
    }

    public static ManagementObjectCollection File(this ManagementScope scope, params object[] args)
    {
        return scope.GetWqlEnumerator(WQL_FILE, args);
    }

    public static string Path(this ManagementBaseObject mo)
    {
        return mo["Path"].ToString().Replace("\\","\\\\");
    }

    public static string Name(this ManagementBaseObject mo)
    {
        return mo["Name"].ToString();
    }

    public static string FileName(this ManagementBaseObject mo)
    {
        return mo["FileName"].ToString();
    }

    public static ulong FreeSpace(this ManagementBaseObject mo)
    {
        return (ulong)mo["FreeSpace"];
    }

    public static ulong Size(this ManagementBaseObject mo)
    {
        return (ulong) mo["Size"];
    }

    public static ulong FileSize(this ManagementBaseObject mo)
    {
        return (ulong) mo["FileSize"];
    }
}

将项目添加到 Listview 的助手

如果需要,这个小助手会处理切换到 UI 线程

// UI Thread safe helper for adding an item
private void Add(string name, ulong size)
{
    if (this.listView1.InvokeRequired)
    {
        this.listView1.Invoke(new MethodInvoker(() => Add(name, size)));
    }
    else
    {
        var lvi = new ListViewItem(name);
        lvi.SubItems.Add(size.ToString());

        this.listView1.Items.Add(lvi);
    }
}

我在RRUZ的这个答案中查找了路径选择问题

于 2014-08-25T14:23:34.177 回答