如何在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));
所以请帮助我克服这个问题。
文件夹没有大小限制,文件夹只是文件的容器,文件的大小决定了文件夹的大小。
要得到整个文件夹的大小,你可以做一个近似,找到磁盘大小和空闲空间,然后减去这两个,就会得到文件夹大小。
在后台扫描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);
这将允许您获取顶级文件夹的"总大小",以字节为单位。