2010-07-08 15 views
9

Je souhaite obtenir le numéro de série du disque dur d'amorçage via une requête WQL.Comment participer à une requête WMI (WQL)

Le démarrage partition peut être récupéré en utilisant la requête suivante:

SELECT * FROM Win32_DiskPartition where BootPartition=True 

Le numéro de série est en Win32_DiskDrive:

SELECT DeviceID, SerialNumber FROM Win32_DiskDrive 

Win32_DiskDriveToDiskPartition présente la cartographie des Win32_DiskDrive-Win32_DiskPartition. Ils sont mis en correspondance Win32_DiskDrive.DeviceID à Win32_DiskPartition.DeviceID dans Win32_DiskDriveToDiskPartition

Comment puis-je construire une requête WQL que les jointures internes Win32_DiskPartition et Win32_DiskDrive? Dois-je utiliser des associateurs ou est-ce que cela fonctionne avec INNER JOIN? WQL ne prend pas en charge la clause JOIN

Répondre

13

Vous devez utiliser la déclaration ASSOCIATORS OF comme vous l'avez deviné. Voici un exemple dans 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 

Notez, cependant, que la propriété Win32_DiskDrive.SerialNumber n'est pas disponible avant Windows Vista. Donc, si vous voulez que votre code fonctionne également sur les versions antérieures de Windows (par exemple Windows XP ou Windows 2000), vous devriez envisager d'utiliser des API autres que WMI.


Edit:(réponse à un commentaire) Oui, vous pouvez ajouter une requête ASSOCIATORS OF imbriqué pour obtenir les Win32_PhysicalMedia instances correspondant aux instances Win32_DiskDrive; quelque chose comme ceci:

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

Vous n'avez pas dit ce que la langue que vous utilisez - Je suppose que dans PowerShell ou C# la chose peut être fait de façon plus élégante, mais VBScript est assez bavard.

+0

Merci beaucoup! Win32_PhysicalMedia est disponible avant Windows Vista, autant que je sache. Dois-je "joindre" ces trois objets WMI via des associateurs pour obtenir la compatibilité avec Windows XP? – j00hi

+0

Vous m'avez beaucoup aidé! Merci! J'ai dû l'écrire en C++, mais la procédure est la même. Je vais poster mon code C++, peut-être que ça pourrait être utile pour quelqu'un. – j00hi

9

Voici le code C++ qui fait la même chose que le code VBScript publié par 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 chose cool est que ce code est compatible avec au moins Windows XP. J'ai testé avec succès ce code sur Win7 64bit, Win7 32bit et WinXP. – j00hi

Questions connexes