2010-07-08 8 views
9

Deseo obtener el número de serie del disco duro de arranque a través de una consulta WQL.Cómo participar en una consulta WMI (WQL)

La bota-partición puede ser recuperada utilizando la siguiente consulta:

SELECT * FROM Win32_DiskPartition where BootPartition=True 

El número de serie se encuentra en Win32_DiskDrive:

SELECT DeviceID, SerialNumber FROM Win32_DiskDrive 

Win32_DiskDriveToDiskPartition tiene el mapeo de Win32_DiskDrive-Win32_DiskPartition. Ellos se asignan a Win32_DiskDrive.DeviceIDWin32_DiskPartition.DeviceID en Win32_DiskDriveToDiskPartition

¿Cómo puedo crear una consulta WQL que une interno Win32_DiskPartition y Win32_DiskDrive? ¿Debo usar Associators o funciona con INNER JOIN?

Respuesta

13

WQL no es compatible con la cláusula JOIN. Necesita usar la declaración ASSOCIATORS OF como lo ha adivinado. He aquí un ejemplo en 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 

Nótese, sin embargo, que la propiedad no está disponible Win32_DiskDrive.SerialNumber anteriores a Windows Vista. Por lo tanto, si desea que su código funcione también en versiones anteriores de Windows (por ejemplo, Windows XP o Windows 2000), debería considerar el uso de API que no sean WMI.


Editar:(Responder al comentario) sí, se puede añadir un ASSOCIATORS OF consulta anidada para obtener los Win32_PhysicalMedia casos correspondientes a los casos Win32_DiskDrive; algo como esto:

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

Usted no ha dicho qué idioma se está utilizando - supongo que en PowerShell o C# todo esto se puede hacer de manera más elegante, pero VBScript es bastante detallado.

+0

Muchas gracias! Win32_PhysicalMedia está disponible antes de Windows Vista, hasta donde yo sé. ¿Tengo que "unirme" a estos tres objetos WMI a través de los asociados para lograr la compatibilidad con Windows XP? – j00hi

+0

¡Me has ayudado mucho! ¡Gracias! Tuve que escribirlo en C++, pero el procedimiento es el mismo. Voy a publicar mi código C++, tal vez podría ser útil para alguien. – j00hi

9

Aquí está el código de C++ que hace lo mismo que el código de VBScript publicado por 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

Lo bueno es que este código es compatible hasta al menos Windows XP. Probé con éxito este código en Win7 64bit, Win7 32bit y WinXP. – j00hi

Cuestiones relacionadas