如何在c#中使用wql实现文件夹大小属性

本文关键字:文件夹 实现 属性 wql | 更新日期: 2023-09-27 18:19:09

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

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

用下面的代码,我可以得到原始文件的大小,但不是所有得到原始文件夹的大小。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";
 }

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

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

所以请帮助我克服这个问题。

如何在c#中使用wql实现文件夹大小属性

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

要得到整个文件夹的大小,你可以做一个近似,找到磁盘大小和空闲空间,然后减去这两个,就会得到文件夹大小

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

调用scan方法。

我确实从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添加条目的helper

这个小助手处理切换到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的回答中查找了一个路径选择问题

问题是,正如@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);

这将允许您获取顶级文件夹的"总大小",以字节为单位。