Russian Qt Forum
Июнь 11, 2024, 10:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: qt wmi опрос системных счетчиков, cpu, ram, hdd и т.д.(не мануал, но подсказка)  (Прочитано 2728 раз)
28515
Гость
« : Февраль 23, 2015, 17:15 »

Не знал куда тему запихнуть, может кому поможет. К сожалению обнаружил, что вопрос до сих пор актуален (особенно у начинающих). Сразу скажу я не гуру, и не претендую...да и просто пофиг. И так, в инете есть одна статья в которой почти все разжевано https://poofeg.ru/2010/06/wmi-i-qt-problemy-s-ienum/, но вопросы почему-то у многих остаются. Понадобится - WMI Code Creator v1.0 http://www.microsoft.com/en-us/download/details.aspx?id=8572. Давайте получим модель проца. В WMI Creator-е выбираем пространство имен root\CIMV2 (почти все что вам понадобится, находится в этом пространстве) выбираем класс Win32_Processor, свойство Name, нажимаем Execute Code - все работает, идем дальше. Собственно сам код(из статьи - могут быть очепятки):
Код:
QAxObject *objIWbemLocator = new QAxObject("WbemScripting.SWbemLocator");
    if (!objIWbemLocator) {
    qDebug("WbemScripting.SWbemLocator not created");
    return 0;
  }
  QAxObject *objWMIService = objIWbemLocator->querySubObject(
          "ConnectServer(QString&,QString&)", //objWMIService - объявляем как переменную член класса, память выделяем в конструкторе
          QString("."), QString("root\\cimv2")); // пространство имен. Если и домен и рабочая группа, можно прикрутить аутентификацию
  if (!objWMIService) {
    qDebug("WMIService not created");
    delete objIWbemLocator;
    return 0;
  }
  QString query = QString( "SELECT * FROM Win32_Processor"); // выбранный класс
  QAxObject *objInterList = objWMIService->querySubObject(
          "ExecQuery(QString&))", query);
  if (!objInterList) {
    qDebug("Answer from ExecQuery is null");
    delete objIWbemLocator;
    return 0;
  }
  if (objInterList->dynamicCall("Count").toInt() == 0) {
    qDebug("Count is 0");
    delete objIWbemLocator;
    return 0;
  }

// И теперь самое интересное

  QAxObject *enum1 = objInterList->querySubObject("_NewEnum");
  if (!enum1) {
    qDebug("Query _NewEnum failed");
    delete objIWbemLocator;
    return 0;
  }
  IEnumVARIANT* enumInterface = 0;
  enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
  if (!enumInterface) {
    qDebug("Query interface failed");
    delete objIWbemLocator;
    return 0;
  }
  enumInterface->Reset();
  QAxObject *item = 0;
  for (int i = 0; i < objInterList->dynamicCall("Count").toInt(); i++) {  
    VARIANT *theItem = (VARIANT*)malloc(sizeof(VARIANT));
    if (enumInterface->Next(1,theItem,NULL) == S_FALSE) {
      qDebug("enum next failed");
      delete theItem;
      delete objIWbemLocator;
      return 0;
    }
    item = new QAxObject((IUnknown*)theItem->punkVal);
    if (!item) {
      qDebug("getting result item failed");
      delete theItem;
      delete objIWbemLocator;
      return 0;
    }
    delete theItem;
    item->dynamicCall("Name").toString(); // это тот Property который выбирали в Creator-е и возвращает модель проца
  }
  delete objIWbemLocator;

Инклуды:
Код:
#include <QAxObject>
#include <QUuid>
#include <qt_windows.h>

pro:
Код:
QT       += axcontainer
Чуть не забыл в начале (в конструкторе) не забываем инициализировать COM библиотеку:
Код:
HRESULT hr = CoInitialize(0);
Теперь про эксепшны.
Сишный код свою часть перекрывает, а wmi нет - если будет исключение в wmi (а оно точно будет) - будет плохо.
Поэтому создаем слот, что то вроде:
Код:
void outputLogError(int num, QString one, QString two, QString three);
и соответственно connect
Код:
connect(objIWbemLocator, SIGNAL(exception(int,QString,QString,QString)), this, SLOT(outputLogError(int,QString,QString,QString)));
Если прям очень нужно могу скинуть свой пример(проверка свободного места на логических дисках по сети), делал для себя и по быстрому поэтому да, там много говнокода.
И самое главное WMI не панацея, и частенько пиз**т, проверено.

Столкнулся с утечкой памяти. Чуть мозг не потек. Долго грешил на QAxObject. Опытным путем установил, что память утекала вот тут
Код:
IEnumVARIANT* enumInterface = 0;
  enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
...
enumInterface->Reset();
потом заподозрил, что дело не в Qt. Благо нашел вот это https://support.microsoft.com/en-us/kb/264295
Цитировать
... but the object won't be released from memory at that point because enumInterface (в моём случае) is still holding a reference to it. When enumInterface->Release(); is called, the ref count will go to 0 and the object will be released. If you omit the enumInterface->Release(); then the enumInterface->Release(); will not free the object and you will have a memory leak in your process.
Надеюсь это кому-нибудь спасёт пару кило нервов и сэкономит пару часов(суток) времени.
« Последнее редактирование: Март 21, 2015, 18:30 от 28515 » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.043 секунд. Запросов: 17.