1

ディレクトリの下にあるすべてのファイルを再帰的に取得しようとしていますC:\YC。リモート コンピュータへの 1 つの WMI 呼び出しにバインドされています。

WQLLIKEオペレーターを使用してこの呼び出しを行うことができましたが、結果が約 6 ファイルであるにもかかわらず、約 30 秒かかります。

// 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 の有無にかかわらず、1 回の 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インスタンスを取得するために呼び出しています。は と の親クラスであり、それ自体が の親です。より単純なオーバーロードを呼び出すこともできますが、それでは不要なインスタンスが 1 つ返されます: 親ディレクトリです。代わりに、 ⇔関係で親になりたいことを指定できるようにする、より長いオーバーロードを呼び出します。 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 に答える