1

我试图递归地获取目录下的所有文件——5 或 6 个文件C:\YC。我被绑定到对远程计算机的一次 WMI 调用。

我设法使用 WQLLIKE运算符进行此调用,但它需要大约 30 秒,即使结果是大约 6 个文件:

// USING A WQL QUERY
string query = "SELECT Name,LastModified FROM CIM_DataFile WHERE PATH LIKE '\\\\YC\\\\%' AND DRIVE ='C:'";
ObjectQuery oQuery = new ObjectQuery();
oQuery.QueryString = query;

ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(scope, oQuery);
oSearcher.Options.Rewindable = false;

// Takes long time
ManagementObjectCollection oReturnCollection = oSearcher.Get();

// SHOWING EACH FILE
foreach (ManagementObject oReturn in oReturnCollection)
{
     Console.WriteLine(oReturn["Name"]?.ToString());
}

是否有一种更有效的方法使用System.Management对象递归地获取文件(使用或不使用 WQL,但使用一个 WMI 调用)?

4

1 回答 1

0

LIKE使用运算符对Name/属性进行过滤时,使用 WMI 查询文件系统似乎非常慢Path,即使过滤器值不包含通配符 ( %)。

这将需要多个查询,但您可以获取基本目录的CIM_Directory(实际上Win32_Directory)实例并自己遍历层次结构......

static void EnumerateDirectory(ManagementObject directory, bool recurse)
{
    // Get all related CIM_LogicalFile instances where this is the parent (GroupComponent)
    // and the related instance is the child (PartComponent)
    using (ManagementObjectCollection children = directory.GetRelated("CIM_LogicalFile", null, null, null, "PartComponent", "GroupComponent", false, null))
        foreach (ManagementObject child in children.Cast<ManagementObject>())
            switch (child.Path.ClassName)
            {
                case "CIM_Directory":
                case "Win32_Directory":
                    Console.WriteLine($"Directory: { child["Name"] }");
                    if (recurse)
                        EnumerateDirectory(child, true);
                    break;
                case "CIM_DataFile":
                    Console.WriteLine($"     File: { child["Name"] }");
                    break;
                default:
                    Console.WriteLine($"ERROR: Unexpected { child.Path.ClassName } instance.  This should never happen!");
                    break;
            }
}

这是调用GetRelated()以获取;相关联的所有CIM_LogicalFile实例。是and的父类,它本身就是 的父类。我们可以调用更简单的重载,但这会返回一个我们不想要的实例:父目录。相反,我们称之为更长的重载,它允许我们指定我们想成为⇔关系中的父级。 directoryCIM_LogicalFileCIM_DataFileCIM_DirectoryWin32_Directorydirectory.GetRelated("CIM_LogicalFile")CIM_DirectorydirectoryCIM_DirectoryCIM_Directory

你会这样打电话EnumerateDirectory()...

static void Main()
{
    const string directoryPath = @"C:\YC";
    ObjectQuery directoryQuery = new SelectQuery(
        "CIM_Directory",
        $"Name = \"{ directoryPath.Replace(@"\", @"\\") }\""
    );

    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(directoryQuery))
    using (ManagementObjectCollection results = searcher.Get())
    using (ManagementObject directory = results.Cast<ManagementObject>().SingleOrDefault())
    {
        if (directory == null)
            Console.WriteLine($"ERROR: The query ' { directoryQuery.QueryString } ' returned no results.");
        else
            EnumerateDirectory(directory, true);
    }
}

如果您只想要目录中的直接子文件,那么代码要简单得多......

static void EnumerateFiles(ManagementObject directory)
{
    using (ManagementObjectCollection children = directory.GetRelated("CIM_DataFile"))
        foreach (ManagementObject child in children.Cast<ManagementObject>())
            Console.WriteLine($"File: { child["Name"] }");
}
于 2021-12-09T13:38:56.960 回答