2010-07-08 18 views
9

Desidero ottenere il numero di serie del disco rigido di avvio tramite una query WQL.Come partecipare a una query WMI (WQL)

Lo stivale-partizione può essere recuperato utilizzando la seguente query:

SELECT * FROM Win32_DiskPartition where BootPartition=True 

Il numero di serie è in Win32_DiskDrive:

SELECT DeviceID, SerialNumber FROM Win32_DiskDrive 

Win32_DiskDriveToDiskPartition ha la mappatura dei Win32_DiskDrive-Win32_DiskPartition. Essi sono mappati Win32_DiskDrive.DeviceID a Win32_DiskPartition.DeviceID in Win32_DiskDriveToDiskPartition

Come posso costruire una query WQL che inner join Win32_DiskPartition e Win32_DiskDrive? Devo usare gli associati o funziona con INNER JOIN?

risposta

13

WQL non supporta la clausola JOIN. Devi usare l'istruzione ASSOCIATORS OF come hai indovinato. Ecco un esempio in 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 

Si noti, tuttavia, che la proprietà Win32_DiskDrive.SerialNumber non è disponibile prima di Windows Vista. Quindi, se vuoi che il tuo codice funzioni anche su versioni precedenti di Windows (ad esempio Windows XP o Windows 2000) dovresti prendere in considerazione l'utilizzo di API diverse da WMI.


Edit:(Rispondi al commento) Sì, è possibile aggiungere un nidificato ASSOCIATORS OF query per ottenere le Win32_PhysicalMedia istanze corrispondenti ai Win32_DiskDrive istanze; qualcosa di simile:

... 
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 

Non hai detto che lingua si sta utilizzando - Credo che in PowerShell o C# il tutto può essere fatto in modo più elegante, ma VBScript è abbastanza prolisso.

+0

Grazie mille! Win32_PhysicalMedia è disponibile prima di Windows Vista, per quanto ne so. Devo "unire" questi tre oggetti WMI tramite gli associati per ottenere la compatibilità con Windows XP? – j00hi

+0

Mi hai aiutato davvero tanto! Grazie! Ho dovuto scriverlo in C++, ma il procedimento è lo stesso. Inserirò il mio codice C++, forse potrebbe essere utile per qualcuno. – j00hi

9

Ecco il codice C++ che fa la stessa cosa del codice VBScript pubblicato da Helen.

// 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 
+0

La cosa interessante è che questo codice è compatibile almeno con Windows XP. Ho testato con successo questo codice su Win7 a 64 bit, Win7 a 32 bit e WinXP. – j00hi