Не знал куда тему запихнуть, может кому поможет. К сожалению обнаружил, что вопрос до сих пор актуален (особенно у начинающих). Сразу скажу я не гуру, и не претендую...да и просто пофиг. И так, в инете есть одна статья в которой почти все разжевано
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:
Чуть не забыл в начале (в конструкторе) не забываем инициализировать 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.
Надеюсь это кому-нибудь спасёт пару кило нервов и сэкономит пару часов(суток) времени.