QFileDialog and COM Object



  • I need help.
    I want to uses WMI in my project for get data about HDDs and write it in file.

    But I have a problem with COM objet and QFileDialog.
    When I initialize COM object after call QFileDialog the initialisation failed, but if I init COM object before call QFileDialog, the window FileDialog don't show.

    can you help me with this problem?
    I specify that my project use Qt 5.3 and my compilator is msvc 2013 64bits



  • @FlaMMe
    https://stackoverflow.com/questions/46581081/qt-qfiledialog-create-unknown-com-object-and-security seems (a) to give you the code for your WMI for free(!) and (b) report exactly the same issue. Read the comments there carefully --- the last one implies to me the OP got it working?

    Otherwise, if you have to I would guess that DontUseNativeDialog would work by avoiding this problem?


  • Qt Champions 2017

    Both looks unrelated to me. Can you show sample code ?



  • @JonB said in QFileDialog and COM Object:

    @FlaMMe
    https://stackoverflow.com/questions/46581081/qt-qfiledialog-create-unknown-com-object-and-security seems (a) to give you the code for your WMI for free(!) and (b) report exactly the same issue. Read the comments there carefully --- the last one implies to me the OP got it working?

    Otherwise, if you have to I would guess that DontUseNativeDialog would work by avoiding this problem?

    Yes I already see this post, it is why I try to initialize COM at the begin of my software, in main.cpp. I will try with the option "DontUseNativeDialog "

    This my class for WMI :

    WMICommunication.h

    
    #include <iostream>
    using namespace std;
    #include <WbemIdl.h>
    #pragma comment(lib, "wbemuuid.lib")
    #include <QDebug>
    
    class WMICommunication
    {
    private:
    
        //Attributes :
        // COM interface pointers
        IWbemLocator         *locator  = nullptr;
        IWbemServices        *services = nullptr;
        IEnumWbemClassObject *results  = nullptr;
        IWbemClassObject     *result   = nullptr;
        bool connected;
    
    
        //Singleton
        static WMICommunication* comm;
        WMICommunication();
        ~WMICommunication();
    
        //Methods
    
    protected :
        bool connect();
        bool disconnect();
    
    public:
        static WMICommunication *getInstance();
        static void deleteInstance();
    
        bool isConnected(){return connected;}
    
    
        bool ExecuteQuery(QString query);
        bool GetAttribut(QString property, QString& result);
        bool NextResult();
    
    
    };
    

    WMICommunication.cpp

    #include "wmicommunication.h"
    #include <QDebug>
    
    
    WMICommunication* WMICommunication::comm = nullptr;
    
    WMICommunication::WMICommunication():
        locator(nullptr),
        services(nullptr),
        results(nullptr),
        result(nullptr)
    {
        comm = this;
        connected = connect();
    }
    
    WMICommunication::~WMICommunication()
    {
        disconnect();
    }
    
    bool WMICommunication::connect()
    {
        // result code from COM calls
            HRESULT hr = 0;
            BSTR resource = SysAllocString(L"ROOT\\CIMV2");
            CoUninitialize();
    
            hr = CoInitializeEx(0, COINIT_MULTITHREADED);
            if (FAILED(hr))
            {
                qDebug() << "Failed to initialize COM library. Error code = 0x"
                   << QString::number( hr, 16 );
              return false;
    
            }
    
            hr = CoInitializeSecurity(nullptr,
                                      -1,
                                      nullptr,
                                      nullptr,
                                      RPC_C_AUTHN_LEVEL_DEFAULT,
                                      RPC_C_IMP_LEVEL_IMPERSONATE,
                                      nullptr,
                                      EOAC_NONE,
                                      nullptr);
            if (FAILED(hr))
            {
               qDebug() << "Failed to initialize security. Error code = 0x"
                     << QString::number( hr, 16 );
               CoUninitialize();
               return false;                  // Program has failed.
            }
            // connect to WMI
            hr = CoCreateInstance(CLSID_WbemAdministrativeLocator,
                                  0,
                                  CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER,
                                  IID_IUnknown,
                                  (LPVOID *) &locator);
            if (FAILED(hr))
            {
               qDebug() << "Failed to initialize locator. Error code = 0x"
                     << QString::number( hr, 16 );
               CoUninitialize();
               return false;                  // Program has failed.
            }
            hr = locator->ConnectServer(resource,
                                        nullptr,
                                        nullptr,
                                        nullptr,
                                        0,
                                        nullptr,
                                        nullptr,
                                        &services);
    
             SysFreeString(resource);
            if (FAILED(hr))
            {
               qDebug() << "Failed to initialize services. Error code = 0x"
                     << QString::number( hr, 16 );
               CoUninitialize();
               return false;                  // Program has failed.
            }
            return true;
    }
    
    bool WMICommunication::disconnect()
    {
        // release WMI COM interfaces
        if (result != nullptr)
            result->Release();
        if (results != nullptr)
            results->Release();
        if (services != nullptr)
            services->Release();
        if (locator != nullptr)
            locator->Release();
    
        // unwind everything else we've allocated
        CoUninitialize();
        return true;
    
    
    }
    
    WMICommunication *WMICommunication::getInstance()
    {
        if (comm == nullptr)
            comm = new WMICommunication();
        return comm;
    
    }
    
    void WMICommunication::deleteInstance()
    {
        if ( comm != nullptr)
        {
            delete comm;
            comm = nullptr;
        }
    }
    
    bool WMICommunication::ExecuteQuery(QString query)
    {
        if (!connected)
            return false;
        if ( services == nullptr)
            return false;
        HRESULT hr =0;
        BSTR language = SysAllocString(L"WQL");
        hr =         hr = services->ExecQuery(language, SysAllocStringByteLen(query.toLatin1().constData(),query.size()), WBEM_FLAG_BIDIRECTIONAL, nullptr, &results);
        SysFreeString(language);
        if (FAILED(hr))
        {
            return false;
        }
    
    return true;
    
    }
    
    bool WMICommunication::GetAttribut(QString property, QString &resultat)
    {
        if ( result != nullptr)
        {
            VARIANT attribut;
            result->Get( reinterpret_cast<LPCWSTR>(property.toLatin1().constData()), 0, &attribut, 0, 0);
            resultat= QString::fromWCharArray(attribut.bstrVal);
            return true;
        }
        else
            return false;
    
    }
    
    bool WMICommunication::NextResult()
    {
        if ( result != nullptr)
            result->Release();
        if ( results == nullptr)
            return false;
        HRESULT hr =0;
        ULONG returnedCount = 0;
        hr = results->Next( WBEM_INFINITE, 1, &result, &returnedCount);
        return( FAILED(hr) == false);
    }
    

    HardDrive.h

    class HardDrive
    {
    private :
        QString name;
        QString caption;
        QString manufacturer;
        QString model;
        QString type;
        QString SN;
    
    public:
        HardDrive();
        HardDrive(const HardDrive &hdd);
    
        QString getName() {return name;}
        void    setName(QString param){name = param;}
    
        QString getCaption(){return caption;}
        void    setCaption(QString param){caption = param;}
    
        QString getManufacturer(){return manufacturer;}
        void    setManufacturer(QString param){manufacturer = param;}
    
        QString getModel() {return model;}
        void    setModel(QString param){model = param;}
    
        QString getType(){return type;}
        void    setType(QString param){type = param;}
    
        QString getSN(){return SN;}
        void    setSN(QString param){SN = param;}
    
        QString toString();
    
    
        static bool ListHardDrive(QVector<HardDrive>& HDDs);
    };
    

    HardDrive.cpp

    HardDrive::HardDrive():
        name(""),
        caption(""),
        manufacturer(""),
        model(""),
        type(""),
        SN("")
    {
    
    }
    
    HardDrive::HardDrive(const HardDrive &hdd):
        name(hdd.name),
        caption(hdd.caption),
        manufacturer(hdd.manufacturer),
        model(hdd.model),
        type(hdd.type),
        SN(hdd.SN)
    {
    
    }
    
    QString HardDrive::toString()
    {
       // ... confidential
       return ""; // so 
    }
    
    bool HardDrive::ListHardDrive(QVector<HardDrive> &HDDs)
    {
    
        if(!WMICommunication::getInstance()->ExecuteQuery("SELECT * FROM Win32_DiskDrive"))
            return false;
        while(WMICommunication::getInstance()->NextResult())
        {
    
            // obtain the desired properties of the next result and print them out
            QString attributs;
            HardDrive hdd;
    
            //Name
            if(!WMICommunication::getInstance()->GetAttribut("Name", attributs))
                return false;
            hdd.setName(attributs);
    
            //caption
            if(!WMICommunication::getInstance()->GetAttribut("Caption", attributs))
                return false;
            hdd.setCaption(attributs);
    
            //caption
            if(!WMICommunication::getInstance()->GetAttribut("Manufacturer", attributs))
                return false;
            hdd.setManufacturer(attributs);
    
    
            //caption
           if(! WMICommunication::getInstance()->GetAttribut("Model", attributs))
               return false;
            hdd.setModel(attributs);
    
    
            //Verification du type
            if(! WMICommunication::getInstance()->GetAttribut("MediaType", attributs))
                    return false;
            hdd.setType(attributs);
            HDDs.push_back(hdd);
        }
    
        WMICommunication::getInstance()->ExecuteQuery("SELECT * FROM Win32_PhysicalMedia");
        int i =0;
        while(WMICommunication::getInstance()->NextResult() && i< HDDs.size())
        {
    
            // obtain the desired properties of the next result and print them out
            QString attributs;
            HardDrive hdd;
    
            //S/N
            if(!WMICommunication::getInstance()->GetAttribut("SerialNumber", attributs))
                return false;
            hdd.setSN(attributs);
    
        }
        return true;
    }
    
    

    In hardware.cpp

    bool Hardware::saveHardwareToFile(QFileInfo file)
    {
        QFile fileHardware(file.absoluteFilePath());
        // we open file and test  opening
        if (!fileHardware.open(QIODevice::WriteOnly | QIODevice::Text))
            return false;
    
        QTextStream flux(&fileHardware);
        flux.setCodec("UTF-8");
        
        QVector<HardDrive> HDDsList;
        HardDrive::ListHardDrive(HDDsList);
        for (int i =0; i < HDDsList.size(); ++i)
            flux << HDDsList.toString() << "\n";
    }
    

    MainWindows.cpp

    void MainWindow::on_pushButton_clicked()
    {
        QString fileName = QFileDialog::getSaveFileName(this, tr("Save Hardware into file"),
                                                        "",
                                                        tr("Text File (*.txt *.TXT)")); // << this windows don't show ! ! ! ! ! 
        Hardware hard;
        hard.saveHardwareToFile(QFileInfo(fileName));
    // ...
    }
    

    I try in main.cpp

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        WMICommunication::getInstance(); // Initialisation WMI 
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    


  • @FlaMMe

    Yes I already see this post, it is why I try to initialize COM at the begin of my software, in main.cpp.

    It always helps when you ask a question if you reference such a post and say if it didn't work....

    I asked you to read the comments there carefully. All I know is it concludes with

    @Daniel thank you. it is done. I put CoUninitialize before my app clossed. – serius777 Oct 5 '17 at 12:10

    which I take to mean the OP solved the issue. Otherwise you know as much as we do about this subject from that thread.



  • @FlaMMe said in QFileDialog and COM Object:

    I will try with the option "DontUseNativeDialog "

    It seems that works with the option "DontUseNativeDialog "



  • @FlaMMe
    Well, yes, because now it's a Qt dialog. The COM part is presumably to do with whatever the Windows native dialog needs to do. It hasn't resolved the problem, but if you're happy avoiding it that's good.



  • Yes, but I will maybe make my own window for select file, because the style of this new window is very different of my software style.

    I however mark the subject as solved.
    Thanks for your help ^^



  • @FlaMMe
    Yes, when you use the internal Qt dialog instead of the native Windows one it looks/behaves differently. That's why I said you could try "DontUseNativeDialog" only if you have to (which seems to be the case because you cannot resolve the COM problem with the native one), and then you'd have to look at it and see how you felt about it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.