【问题标题】:How to join in a WMI Query (WQL)如何加入 WMI 查询 (WQL)
【发布时间】:2011-03-13 12:28:42
【问题描述】:

我想通过 WQL 查询获取引导硬盘的序列号。

可以使用以下查询检索引导分区:

SELECT * FROM Win32_DiskPartition where BootPartition=True

序列号在 Win32_DiskDrive 中:

SELECT DeviceID, SerialNumber FROM Win32_DiskDrive

Win32_DiskDriveToDiskPartition 具有Win32_DiskDriveWin32_DiskPartition 的映射。 它们在Win32_DiskDriveToDiskPartition 中映射为Win32_DiskDrive.DeviceIDWin32_DiskPartition.DeviceID

如何构建一个内部连接 ​​Win32_DiskPartitionWin32_DiskDrive 的 WQL 查询? 我必须使用关联器还是与 INNER JOIN 一起使用?

【问题讨论】:

    标签: c++ vbscript wmi wql


    【解决方案1】:

    WQL 不支持JOIN 子句。如您所料,您需要使用ASSOCIATORS OF 语句。这是 VBScript 中的一个示例:

    strComputer = "." 
    Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
    
    Set colPartitions = oWMI.ExecQuery( _
        "SELECT * FROM Win32_DiskPartition WHERE BootPartition=True") 
    
    For Each oPartition in colPartitions 
    
        Set colDrives = oWMI.ExecQuery( _
            "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" _
            & oPartition.DeviceID & "'} WHERE ResultClass=Win32_DiskDrive")
    
        For Each oDrive in colDrives
            WScript.Echo oDrive.SerialNumber
        Next
    
    Next
    

    但是请注意,Win32_DiskDrive.SerialNumber 属性在 Windows Vista 之前不可用。因此,如果您希望您的代码也适用于早期的 Windows 版本(例如 Windows XP 或 Windows 2000),您应该考虑使用 WMI 以外的 API。


    编辑: (回复评论) 是的,您可以添加嵌套的ASSOCIATORS OF 查询来获取与Win32_DiskDrive 实例对应的Win32_PhysicalMedia 实例;像这样:

    ...
    For Each oDrive in colDrives
        Set colMedia = oWMI.ExecQuery( _
            "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" _
            & oDrive.DeviceID & "'} WHERE ResultClass=Win32_PhysicalMedia")
    
        For Each oMedia in colMedia
            WScript.Echo oMedia.SerialNumber
        Next
    Next
    

    你还没有说你使用的是什么语言 - 我猜在 PowerShell 或 C# 中,整个事情可以更优雅地完成,但 VBScript 相当冗长。

    【讨论】:

    • 非常感谢!据我所知,Win32_PhysicalMedia 在 Windows Vista 之前可用。我是否必须通过关联器“加入”这三个 WMI 对象才能实现与 Windows XP 的兼容性?
    • 你帮了我很多!谢谢!我不得不用 C++ 编写它,但过程是一样的。我将发布我的 C++ 代码,也许它可能对某人有用。
    【解决方案2】:

    这是与 Helen 发布的 VBScript 代码执行相同操作的 C++ 代码。

    // Obtain the initial locator to WMI
    // ...
    // Connect to WMI through the IWbemLocator::ConnectServer method
    // ...
    // Set security levels on the proxy
    // ...
    
    wchar_t wmihddsn[256];
        *wmihddsn=0;
    
    hres = pSvc->ExecQuery(
        bstr_t("WQL"),
        bstr_t("SELECT * FROM Win32_DiskPartition WHERE BootPartition=True"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    if(SUCCEEDED(hres) && pEnumerator) 
    {
        // get the first Win32_DiskPartition
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
    
        if(SUCCEEDED(hr) && 0 != uReturn)
        {
            VARIANT vtProp;
            wchar_t tmp[1024];
            char query[1024];
    
            // Get the value of the partition's DeviceID property
            hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);
            if(SUCCEEDED(hr))
            {
                if(vtProp.vt == VT_BSTR) {
                    // wcout << " SerialNumber : " << vtProp.bstrVal << endl;
                    wcscpy(tmp, vtProp.bstrVal);
                }
                VariantClear(&vtProp);
    
    
                // "join" Win32_DiskPartition to Win32_DiskDrive
                sprintf(query, 
                    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='%s'} WHERE ResultClass=Win32_DiskDrive",
                    NarrowWcharString(tmp));
    
                hres = pSvc->ExecQuery(
                    bstr_t("WQL"),
                    bstr_t(query),
                    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
                    NULL,
                    &pEnumerator1);
    
                if(SUCCEEDED(hres) && pEnumerator1)
                {
                    // get the first Win32_DiskDrive
                    hr = pEnumerator1->Next(WBEM_INFINITE, 1, &pclsObj1, &uReturn);
    
                    if(SUCCEEDED(hr) && 0 != uReturn)
                    {
                        // Get the value of the disk-drive's DeviceID
                        hr = pclsObj1->Get(L"DeviceID", 0, &vtProp, 0, 0);
                        if(SUCCEEDED(hr))
                        {
                            if(vtProp.vt == VT_BSTR)
                            {
                                wcscpy(tmp, vtProp.bstrVal);
                            }
                            VariantClear(&vtProp);
    
    
                            // "join" Win32_DiskDrive to Win32_PhysicalMedia
                            sprintf(query,
                                "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='%s'} WHERE ResultClass=Win32_PhysicalMedia",
                                NarrowWcharString(tmp));
    
                            hres = pSvc->ExecQuery(
                                bstr_t("WQL"),
                                bstr_t(query),
                                WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
                                NULL,
                                &pEnumerator2);
    
                            if(SUCCEEDED(hres) && pEnumerator2)
                            {
                                // get the first Win32_PhysicalMedia
                                hr = pEnumerator2->Next(WBEM_INFINITE, 1, &pclsObj2, &uReturn);
    
                                if(SUCCEEDED(hr) && 0 != uReturn)
                                {
                                    // get the PhysicalMedia's SerialNumber
                                    hr = pclsObj2->Get(L"SerialNumber", 0, &vtProp, 0, 0);
                                    if(SUCCEEDED(hr))
                                    {
                                        if(vtProp.vt == VT_BSTR) 
                                        {
                                            // wcout << " SerialNumber : " << vtProp.bstrVal << endl;
                                            wcscpy(wmihddsn,vtProp.bstrVal);
                                        }
                                        VariantClear(&vtProp);
                                    }
    
                                }
    
                                if(pclsObj2) pclsObj2->Release();
                            }
                            if(pEnumerator2) pEnumerator2->Release();
    
                        } // get disk-drive's DeviceID
                    }
    
                    if(pclsObj1) pclsObj1->Release();
                }
                if(pEnumerator1) pEnumerator1->Release();
    
            } // get partition's DeviceID
        }
    
        if(pclsObj) pclsObj->Release();
    } // if succeeded first query
    if(pEnumerator) pEnumerator->Release();
    
    // ...
    // cleanup
    

    【讨论】:

    • 很酷的是,这段代码至少兼容 Windows XP。我在 Win7 64bit、Win7 32bit 和 WinXP 上成功测试了这段代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多