none
ISensLogon interface RRS feed

  • Вопрос

  • Hi all. I need to use ISensLogon interface. How shoud i use it in c++?

    I found example ISensNetwork. But don't understand it completely.

    I am trying to use ISensLogon by this way:

    class SysEvent : public IDispatchImpl<ISensLogon, &IID_ISensLogon, &LIBID_SensEvents, 1, 0> { //! Construction and destruction. public: //! Constructor. SysEvent() {} //! Destructor. ~SysEvent() {} //! Public interface. public: virtual HRESULT STDMETHODCALLTYPE Logon(BSTR bstrUserName) {}

    virtual HRESULT STDMETHODCALLTYPE Logoff(BSTR bstrUserName) {}

    virtual HRESULT STDMETHODCALLTYPE StartShell(BSTR bstrUserName) {}

    virtual HRESULT STDMETHODCALLTYPE DisplayLock(BSTR bstrUserName) {}

    virtual HRESULT STDMETHODCALLTYPE DisplayUnlock(BSTR bstrUserName) {} virtual HRESULT STDMETHODCALLTYPE StartScreenSaver(BSTR bstrUserName) {} virtual HRESULT STDMETHODCALLTYPE StopScreenSaver(BSTR bstrUserName) {} };

    class SysEventRegistrar
    {
    //! Construction and destruction.
    public:
    //! Constructor.
    SysEventRegistrar() {}
    //! Destructor.
    ~SysEventRegistrar() {}

    //! Private interface.
    private:
    void Register();
    void Unregister() {}

    //! Private data members.
    private:
    SysEvent *pISensLogon;
    IEventSystem *pIEventSystem;
    IEventSubscription* pIEventSubscription;
    };

    void SysEventRegistrar::Register()
    {
    HRESULT res;
    res = CoCreateInstance(CLSID_CEventSystem, 0, CLSCTX_SERVER, IID_IEventSystem, (void**)&pIEventSystem);
    if (res != S_OK || !pIEventSystem)
    return;

    pISensLogon.CoCreateInstance(IID_ISensLogon);

    pISensLogon= new SysEvent(); // Error during compilation see below
    if (!pISensLogon)
    return;

    /* Some other code */

    }

    When i am trying to compile project i am getting error:

    19>..\SysEventRegistrar.cpp(42): error C2259: 'SysEvent' : cannot instantiate abstract class
    19>          due to following members:
    19>          'HRESULT IUnknown::QueryInterface(const IID &,void **)' : is abstract
    19>          C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.h(116) : see declaration of 'IUnknown::QueryInterface'
    19>          'ULONG IUnknown::AddRef(void)' : is abstract
    19>          C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.h(120) : see declaration of 'IUnknown::AddRef'
    19>          'ULONG IUnknown::Release(void)' : is abstract
    19>          C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.h(122) : see declaration of 'IUnknown::Release'

    At this line:

    pISensLogon= new SysEvent();
    What am I doing wrong?. Thanks.





    • Изменено Oleg Kolomiytsev 21 декабря 2015 г. 10:32 Problem was explained more clearly
    17 декабря 2015 г. 22:26

Ответы

  • В статье, на которую Вы ссылаетесь, автор не использует ATL и реализует все интерфейсы самостоятельно, правда несколько "диким" способом :) Поэтому его класс не является абстрактным и допускает создание объектов с помощью new.

    В идеологии ATL класс должен быть наследником нескольких библиотечных классов (см. здесь), а объект класса создается еще одним шаблоном CComObject (вернее, его методом CreateInstance), который реализует интерфейс IUnknown.

    Если хотите еще больше "упростить себе жизнь", можете познакомиться с созданием компонентов при помощи атрибутов.

    В любом случае, понимание технологии COM очень желательно.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!


    • Изменено kosuke904 22 декабря 2015 г. 6:05 добавлена ссылка
    • Помечено в качестве ответа Oleg Kolomiytsev 27 декабря 2015 г. 18:00
    22 декабря 2015 г. 5:57

Все ответы

  • Здравствуйте. Если коротко, то объект класса компонента не создается операцией new. А, вообще, для решения подобной задачи Вам следует познакомиться с основами технологии COM и библиотекой ATL. Только после этого разговор будет иметь смысл.

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!


    • Изменено kosuke904 21 декабря 2015 г. 18:20 уточнение
    21 декабря 2015 г. 18:19
  • Мне это тоже показалось странным я руководствовался примером ISensNetwork и ISensLogon а также некоторыми другими, во всех них для создания "sink object with an implementation for each interface that you handle" (c) MSDN использовалась оператор new. Для этого я и создал тему. Использовать CoCreateInstanse для создания ISensLogon интерфейса у меня не получается...
    21 декабря 2015 г. 20:12
  • В статье, на которую Вы ссылаетесь, автор не использует ATL и реализует все интерфейсы самостоятельно, правда несколько "диким" способом :) Поэтому его класс не является абстрактным и допускает создание объектов с помощью new.

    В идеологии ATL класс должен быть наследником нескольких библиотечных классов (см. здесь), а объект класса создается еще одним шаблоном CComObject (вернее, его методом CreateInstance), который реализует интерфейс IUnknown.

    Если хотите еще больше "упростить себе жизнь", можете познакомиться с созданием компонентов при помощи атрибутов.

    В любом случае, понимание технологии COM очень желательно.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!


    • Изменено kosuke904 22 декабря 2015 г. 6:05 добавлена ссылка
    • Помечено в качестве ответа Oleg Kolomiytsev 27 декабря 2015 г. 18:00
    22 декабря 2015 г. 5:57
  • class CNetwork : public CComObjectRootEx<CComSingleThreadModel>, public IDispatchImpl<ISensNetwork, &IID_ISensNetwork, &LIBID_SensEvents, 1, 0> { //! Construction and destruction. public: //! Constructor. CNetwork() {} //! Destructor. ~CNetwork() {} BEGIN_COM_MAP(CNetwork) COM_INTERFACE_ENTRY(ISensNetwork) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() virtual HRESULT STDMETHODCALLTYPE ConnectionMade( BSTR bstrConnection, ULONG ulType, SENS_QOCINFO* lpQOCInfo) {} virtual HRESULT STDMETHODCALLTYPE ConnectionMadeNoQOCInfo( BSTR bstrConnection, ULONG ulType) {} virtual HRESULT STDMETHODCALLTYPE ConnectionLost( BSTR bstrConnection, ULONG ulType) {} virtual HRESULT STDMETHODCALLTYPE DestinationReachable( BSTR bstrDestination, BSTR bstrConnection, ULONG ulType, SENS_QOCINFO * lpQOCInfo) {} virtual HRESULT STDMETHODCALLTYPE DestinationReachableNoQOCInfo( BSTR bstrDestination, BSTR bstrConnection, ULONG ulType) {} }; class NetworkProvider { public: //!Constructor. NetworkProvider(HWND hwnd) {} //! Destructor. ~NetworkProvider() {} // // Public interface. // public: //! Registers. void Register(); //! Unregisters. void Unregister() {} private: //! ISens event system pointer. CComPtr<IEventSystem> pIEventSystem_; //! ISens_Network interface pointer. CComObject<CNetwork>* networkObj_; };

    static wchar_t* methods[]={
    L"ConnectionMade",
    L"ConnectionMadeNoQOCInfo",
    L"ConnectionLost",
    L"DestinationReachable",
    L"DestinationReachableNoQOCInfo"};

    static wchar_t* names[] = {
    L"HB_ConnectionMade",
    L"HB_ConnectionMadeNoQOCInfo",
    L"HB_ConnectionLost",
    L"HB_DestinationReachable",
    L"HB_DestinationReachableNoQOCInfo"};

    static wchar_t* subids[]= {
    L"{cd1dcbd6-a14d-4823-a0d2-8473afde360f}",
    L"{C4CEE207-5021-4948-99EA-DE6D8E537DB3}",
    L"{77405340-F779-4E3C-B2D6-E9890B19333D}",
    L"{EFAD2171-191D-48AF-875D-7468BB3A8051}",
    L"{51A05BC8-BDCC-475F-BBF5-8DFCDB9C824C}"};


    void NetworkProvider::Register() { if (FAILED(CoCreateInstance( CLSID_CEventSystem, NULL, CLSCTX_SERVER, IID_IEventSystem, reinterpret_cast<void**>(&pIEventSystem_)))) BOOST_THROW_EXCEPTION(std::runtime_error("Unable to create system event instance")); if (FAILED(CComObject<CNetwork>::CreateInstance(&networkObj_))) BOOST_THROW_EXCEPTION(std::runtime_error("Unable to create network interface instance")); networkObj_->AddRef(); HRESULT hr = E_FAIL; if (pIEventSystem_) { CComPtr<IEventSubscription> pIEventSubscription; for (int i = 0; i < 4; i++) { hr = pIEventSubscription.CoCreateInstance(CLSID_CEventSubscription, NULL, CLSCTX_SERVER); if (FAILED(hr)) continue; hr = pIEventSubscription->put_EventClassID(L"{d5978620-5b9f-11d1-8dd2-00aa004abd5e}" /* SENSGUID_EVENTCLASS_NETWORK */); if (FAILED(hr)) break; hr = pIEventSubscription->put_SubscriberInterface(networkObj_->GetUnknown()); if (FAILED(hr)) break; hr = pIEventSubscription->put_MethodName(methods[i]); if (FAILED(hr)) break; hr = pIEventSubscription->put_SubscriptionName(names[i]); if (FAILED(hr)) break; hr = pIEventSubscription->put_SubscriptionID(subids[i]); if (FAILED(hr)) break; hr = pIEventSubscription->put_PerUser(TRUE); if (FAILED(hr)) break; hr = pIEventSystem_->Store(PROGID_EventSubscription, (IUnknown*)pIEventSubscription); if (FAILED(hr)) break; pIEventSubscription.Release(); } if (pIEventSubscription) pIEventSubscription.Release(); } }

    Вот что получилось решил писать пример для ISens_Network так как его проще тестировать.

    Возникли некоторые вопросы:

    1. При такой реализации ивенты почему-то приходят не всегда... что я сделал не так?

    2. Можно ли CComObject<CNetwork>* networkObj_ определить как CComPtr<CComObject<CNetwork>> networkObj_ будет ли это все дело работать?

    3. Массив methods[] должен содержать имена виртуальных методов интерфейса?

    4. Массив names[] может принимать любые значения?

    5. Массив subids[]  может принимать любой uuid? или есть какие-то предопределенные?







    • Изменено Oleg Kolomiytsev 22 декабря 2015 г. 19:06 More readable form
    22 декабря 2015 г. 12:18
  • Hey guys. Could you help me?
    24 декабря 2015 г. 22:36
  • Hey guys. Could you help me?

    Здравствуйте. Уведомление о Вашем сообщении получил лишь сегодня. Мне нужно посмотреть документацию, чтобы ответить. Отпишусь позднее.

    Одна очевидная ошибка в Вашем коде: цикл for делает лишь 4 итерации, поэтому регистрируются не все методы.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    25 декабря 2015 г. 7:22
  • void NetworkProvider::Register()
    {
    	if (FAILED(CoCreateInstance(
    		CLSID_CEventSystem, NULL, CLSCTX_SERVER, IID_IEventSystem, reinterpret_cast<void**>(&pIEventSystem_))))
    		BOOST_THROW_EXCEPTION(std::runtime_error("Unable to create system event instance"));
    
    	if (FAILED(CComObject<CNetwork>::CreateInstance(&networkObj_)))
    		BOOST_THROW_EXCEPTION(std::runtime_error("Unable to create network interface instance"));
    
    	networkObj_->AddRef();
    
    	networkObj_->DoOnConnectionMade(boost::bind(&NetworkProvider::HandleConnectionMade, this, _1));
    	networkObj_->DoOnConnectionLost(boost::bind(&NetworkProvider::HandleConnectioLost, this, _1));
    	networkObj_->DoOnConnectionMadeNoQOCInfo(boost::bind(
    		&NetworkProvider::HandleConnectionMadeNoQOCInfo, this, _1));
    
    	HRESULT hr = E_FAIL;
    	if (pIEventSystem_)
    	{
    		CComPtr<IEventSubscription> pIEventSubscription;
    		for (int i = 0; i <= 4; ++i)
    		{
    			hr = pIEventSubscription.CoCreateInstance(CLSID_CEventSubscription, NULL, CLSCTX_SERVER);
    			if (FAILED(hr))
    				continue;
    
    			hr = pIEventSubscription->put_EventClassID(L"{d5978620-5b9f-11d1-8dd2-00aa004abd5e}" /* SENSGUID_EVENTCLASS_NETWORK */);
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSubscription->put_SubscriberInterface(networkObj_->GetUnknown());
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSubscription->put_MethodName(methods[i]);
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSubscription->put_SubscriptionName(names[i]);
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSubscription->put_SubscriptionID(subids[i]);
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSubscription->put_PerUser(TRUE);
    			if (FAILED(hr))
    				break;
    
    			hr = pIEventSystem_->Store(PROGID_EventSubscription, (IUnknown*)pIEventSubscription);
    			if (FAILED(hr))
    				break;
    
    			pIEventSubscription.Release();
    		}
    
    		if (pIEventSubscription)
    			pIEventSubscription.Release();
    	}
    }

    Поменял цикл for() для 5ти ивентов. Тестировал на виртуальной машине на Windows10, Windows7.

    1.

    - На Windows10 нормально отрабатывают все ивенты.

    - A вот на Windows7 ивенты то приходят то нет, очень странной, такое наблюдается только для виртуальной машины на Windows7 если это не виртуальная машина ивенты приходят нормально.

    Возможно какая-то загадка кроется в VMware - не могу понять...

    Или я не то возвращаю из метода обработчика события:

    HRESULT CNetwork::ConnectionLost(BSTR bstrConnection, ULONG ulType)
    {
            /* Some code */
    	return S_OK;
    }

    2.

    Так же остается непонятным почему для значений этих массивов: methods[], names[]subids[] не определены константы?




    25 декабря 2015 г. 10:17
  • По поводу деталей (methods, names и проч.) подписки на события COM+ ничего сказать не могу, не разбирался в этом вопросе. Вот ссылка на документацию, посмотрите.

    Шаблон CComPtr предназначен для того, чтобы не думать о подсчете ссылок (AddRef, Release) при использовании указателя на интерфейс. Думаю, что и для CComObject-а можно его применить.

    По поводу разницы в поведении OC также сказать сложно. Может быть подсистема COM+ настроена по-разному, может быть брандмауэр блокирует ее активность... Читайте документацию, там должны быть ответы на все вопросы :)

    Считаю, что тема, с которой Вы начали этот топик, исчерпана (код скомпилирован, события Вы получаете) Новые вопросы формулируйте в новых темах, а эту можно закрыть.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    25 декабря 2015 г. 13:32