【问题标题】:Getting MSFT_Partition from MSFT_Disk using Associators使用关联器从 MSFT_Disk 获取 MSFT_Partition
【发布时间】:2021-01-22 22:31:42
【问题描述】:

我正在尝试从MSFT_Disk 对象中获取MSFT_Partitions 的列表并遍历它们。 这是我到目前为止一直在使用的代码,但它总是输出System.Management.ManagementException: 'Invalid query ' 异常。

这是我目前正在使用的代码:

public static void GetDiskInfo() {
    var rawDiskInfos = new ManagementObjectSearcher("root\\Microsoft\\Windows\\Storage", "SELECT * FROM MSFT_Disk");
    foreach(var rawDiskInfo in rawDiskInfos.Get()) {
        Console.WriteLine(rawDiskInfo["FriendlyName"]);
        GetPartitionInfo(rawDiskInfo["ObjectId"]);
    }
}

public static void GetPartitionInfo(object objectId) {
    ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\Microsoft\\Windows\\Storage");

    var query = new ObjectQuery("ASSOCIATORS OF {MSFT_Disk.ObjectId=\"" + objectId + "\"} WHERE AssocClass = MSFT_DiskToPartition");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    ManagementObjectCollection queryCollection = searcher.Get();

    foreach(var partiton in queryCollection) {
        Console.WriteLine(partiton["Guid"]);
    }
}

我已经尝试了很多我在网上找到的解决方案,但所有解决方案都导致了相同的异常。

非常感谢您的帮助!

【问题讨论】:

    标签: c# winapi wmi


    【解决方案1】:

    您在 Internet 上找到的大多数查询都不会这样做,但在一般情况下,您必须使用 @987654321 转义传递给 WQL 查询的原始字符串(在您的情况下,objectId 包含特殊字符) @,使用这样的方法:

    public static string EscapeWql(string text)
    {
        if (text == null)
            return null;
    
        var sb = new StringBuilder(text.Length);
        foreach (var c in text)
        {
            if (c == '\\' || c == '\'' || c == '"')
            {
                sb.Append('\\');
            }
            sb.Append(c);
        }
        return sb.ToString();
    }
    

    所以你的方法现在应该是这样的:

    public static void GetPartitionInfo(object objectId)
    {
        var scope = new ManagementScope(@"root\Microsoft\Windows\Storage");
        var query = new ObjectQuery("ASSOCIATORS OF {MSFT_Disk.ObjectId=\"" + EscapeWql((string)objectId) + "\"} WHERE AssocClass = MSFT_DiskToPartition");
        using (var searcher = new ManagementObjectSearcher(scope, query))
        {
            using (var queryCollection = searcher.Get())
            {
                foreach (var partition in queryCollection)
                {
                    Console.WriteLine(partition["Guid"]);
                }
            }
        }
    }
    

    PS:不要忘记在 IDisposable 类上使用语句。

    【讨论】:

    • 非常感谢您的帮助,它运行良好!使用 IDisposable 类有什么好处?它提高了性能吗?
    • 不,它会释放 .NET 类持有的(非托管)资源,因此当您使用完一次性实例后,最好将其丢弃:docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
    • 哇,答案很快。感谢您的所有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多