FantomCat
Гость
|
|
« : 15-12-2003 10:38 » |
|
Здравствуйте! Покажите мне пожалуйста, где я торможу. У меня ехе-сервер, который должен оповещать всех клиентов о чем-то. Но так получается, что на событи реагирует только тот клиент, по инициативе которого было сгенерировано событие. А надо, чтобы все реагировали. Вот привожу кусочки исходников на более простеньком примере, чем мне надо. кокласс интерфейса сервера class ATL_NO_VTABLE CSender : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CSender, &CLSID_Sender>, public IConnectionPointContainerImpl<CSender>, public ISender, public CProxy_ISenderEvents< CSender > { public: CSender() { } DECLARE_REGISTRY_RESOURCEID(IDR_SENDER) DECLARE_NOT_AGGREGATABLE(CSender) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CSender) COM_INTERFACE_ENTRY(ISender) COM_INTERFACE_ENTRY(IConnectionPointContainer) COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) END_COM_MAP() BEGIN_CONNECTION_POINT_MAP(CSender) CONNECTION_POINT_ENTRY(DIID__ISenderEvents) END_CONNECTION_POINT_MAP() // ISender public: STDMETHOD(SendMsg)(/*[in]*/BSTR msg); }; template <class T>// это визард формировал class CProxy_ISenderEvents : public IConnectionPointImpl<T, &DIID__ISenderEvents, CComDynamicUnkArray> { //Warning this class may be recreated by the wizard. public: HRESULT Fire_SendCallBack(BSTR msg) { CComVariant varResult; T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[1]; int nConnections = m_vec.GetSize(); FILE*f = fopen("conn","w"); fprintf(f,"%d\n",nConnections); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { VariantClear(&varResult); pvars[0] = msg; DISPPARAMS disp = { pvars, NULL, 1, 0 }; pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL); fprintf(f,"%x\n",pDispatch); } } fclose(f); delete[] pvars; return varResult.scode; } }; Ну и вызов самого события STDMETHODIMP CSender::SendMsg(BSTR msg) { Fire_SendCallBack(msg); return S_OK; } Кто-нибудь уже станкивался с таким, или проще свой коннекшнпоинт реализовать? А ведь не хочется.
|
|
|
Записан
|
|
|
|
Anonymous
Гость
|
|
« Ответ #1 : 17-12-2003 02:43 » |
|
Тут DECLARE_CLASSFACTORY_SINGLETON должен помочь
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #2 : 17-12-2003 07:51 » |
|
Не помогает.... Почему-то на каждого клиента создается свой экземпляр кокласса. А там у каждого свой m_vec, в котором только один элемент. Вот оно так и получается, что событие отправляет только себе. ЛЮДИ!!! Что делать!!!! Помогите!!!! плз!!!
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #3 : 17-12-2003 08:33 » |
|
Тут DECLARE_CLASSFACTORY_SINGLETON должен помочь
Не помогает....
Хм... Попробуй в dcomcnfg поменять галку "The launching user" на любую другую, потому как по умолчанию для запуска используется учетная запись активатора, а поэтому экземпляров может быть много. Еще можно ROT использовать(RegisterActiveObject/GetActiveObject).
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #4 : 17-12-2003 10:57 » |
|
Старнная вещь этот мелкомягкий компилятор - помогло с 3-го раза. Теперь буду биться , как заадвайзиться к событиям на удаленном серере. Так что ждите вопросов. Можно отвечать уже сейчас
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #5 : 17-12-2003 11:10 » |
|
Старнная вещь этот мелкомягкий компилятор - помогло с 3-го раза.
А что помогло ? Теперь буду биться , как заадвайзиться к событиям на удаленном серере. Так что ждите вопросов. Можно отвечать уже сейчас
Точно будут проблемы с безопасностью. Кое-что есть тут https://forum.shelek.ru/index.php/topic,748.0.html
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #6 : 17-12-2003 14:58 » |
|
помогло DECLARE_CLASSFACTORY_SINGLETON Ну, а теперь ,как и было обещано, вопросы. Не хочет мой клиент адвайзиться к событиям на удаленном сервере. Сам сервак там загружается, све методы доступны, но с событиями никак В настройках DCOM'a стоит, что запускать можно всем. Делаю даже CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); И ниче!!!!... Возвращает HRESULT типа -12хххххх. И че делать?
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #7 : 18-12-2003 06:02 » |
|
Не хочет мой клиент адвайзиться к событиям на удаленном сервере. Сам сервак там загружается, све методы доступны, но с событиями никак В настройках DCOM'a стоит, что запускать можно всем. Делаю даже CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); И ниче!!!!... Возвращает HRESULT типа -12хххххх. И че делать?
А точный HRESULT как выглядит ? CoInitializeSecurity нужно вызывать как на сервере, так и на клиенте. Кстати на каких осях работают client/server ? Почти 100% способ - В фунцию Advise(IUnknown* pUnkSink, DWORD* pdwCookie) после вызова GetConnectionInterface нужно вставить следующий код: CoSetProxyBlanket(pUnkSink, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
где pUnkSink первый параметр Advise. Потом добавить во все методы рассылки сообщений(имеют названия типа Fire_EventX, хотя могут быть и другие ) перед вызовом pDispatch->Invoke код CoSetProxyBlanket(pDispatch, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
Если так не заработает, будем думать дальше...
|
|
« Последнее редактирование: 23-11-2007 15:43 от Алексей1153++ »
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #8 : 18-12-2003 08:11 » |
|
На счет HRESULT'a вру немного, возвращает -2147023149. А на счет остального. Сервак у меня работает под XP, а клиент должен на любой пахать, вот и пробую под 98-й. Если я правильно понимаю, мне у клиента надо свой DispEventAdvise реализовать? Ну щас попробую. Что выйдет, напишу. Спасибки огромное за советы!
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #9 : 18-12-2003 08:22 » |
|
На счет HRESULT'a вру немного, возвращает -2147023149. А на счет остального. Сервак у меня работает под XP, а клиент должен на любой пахать, вот и пробую под 98-й.
Ой, как все запущенно... Ну зачем сразу под 98-й(а DCOM там стоит ?). Поэтому и HRESULT такой(RPC_S_UNKNOWN_AUTHN_SERVICE ). Если есть возможность лучше сначала на любой NT проверять.
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #10 : 18-12-2003 16:56 » |
|
Е-мае! Ну и денек! DCOM на 98-й отсутствует, в этом весь и прикол! Но к серваку коннектится, и все методы его доступны! Кстати, чей DCOM нормальный? Тошо ставить все равно придется. Но этим же все не закончилось. Поставила я себе 2000-ную винду седня. Так эта гадость вообще грузить сервер теперь не хочет (даже локально! 8-(ж). Возвашает -2147023149 родненькое. Вроде и и DCOM'e настройки нормальные поставила. Может че еще не хватает? Тошо под ХР локально работает, а вот удаленно не хочет вообще 8-(. Крыша едет, а до понедельника нуно полностью работоспособную прогу сдать! NetRaider, может ты мне еще че-нить умного подскажешь, а то я сегодня чувствую себя таким ламером!!!
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #11 : 19-12-2003 08:08 » |
|
Поставила я себе 2000-ную винду седня. Так эта гадость вообще грузить сервер теперь не хочет (даже локально! 8-(ж). Возвашает -2147023149 родненькое. Вроде и и DCOM'e настройки нормальные поставила. Может че еще не хватает? Тошо под ХР локально работает, а вот удаленно не хочет вообще 8-(.
Кто(функция) и где (подозреваю, что на клиенте) выдает -2147023149 ? Ок, давай сначала(я точно у тебя ситуацию не знаю, если что поправишь) Так, как сервер ATL, то проблем с регистрацией в реестре быть не должно... На той машине, где запускается сервер в dcomcnfg стоит галка 'Разрешить использование DCOM(как точно пишется не помню, в реестре это - HKEY_LOCAL_MACHINE\Software\Microsoft\OLE\EnableRemoteConnect)' ? Проидись по коду, посмотри, - после вызова каждой ф-ий должна быть проверка а-ля if(FAILED(hr)), а то может быть еще раньше вылетает и с другим кодом ошибки. Если на защиту глубоко наплевать, тогда нужно на клиенте и на сервере вызывать CoInitializeSecurity (см.выше) , если не помогает - попробуй поиграться со вкладками безопасности в dcomcnfg для твоего сервера(кто может запускать сервер, кто имеет доступ к нему). Также надо проверить права доступа на сам exe-файл сервера. Можно включить на сервере аудит событий logon/logoff чтобы определить, под какой учетной записью клиент обращается к серверу. Сначала надо добится, чтобы экземпляр объекта успешно создавался. Потом надо пытаться вызывать простые функции(не connection points). Если и это работает - тогда переходить к отладке точек подключения. Если будут вопросы - постарайся написать как можно больше информации, а то гадать приходитсь.
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #12 : 19-12-2003 08:24 » |
|
Кстати - а компьютеры входят в домен ?
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #13 : 19-12-2003 08:55 » |
|
Крыша едет! NetRaider, у тебя потрясающая интуиция! Все имеено так. В реестре все стоит, параметры в dcomnfg такие давно выставлены. На безопасность глубоко наплевать, поэтому стоит разрешение на запуск и доступ всем, компы в домен входят. CoInitializeSecurity вызываю с обеих сторон. И.... Короче на 98-й уже и DCOM новый поставила, а одна фигня - к событиям не подключается, хотя сервак грузится и все методы доступны и работают нормально. А вот с 2000-ной еще не разобралась. Не продуплю что-то с настройками. Даже локально сервак не грузится и ни одна моя прога с OLE - автоматизацией не пашет, как только вызываю какой-нить сервер - пишет Access denied. Щас еще чего-нибудь сделать ему попробую и буду биться головой об монитор
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #14 : 19-12-2003 09:07 » |
|
Короче на 98-й уже и DCOM новый поставила, а одна фигня - к событиям не подключается, хотя сервак грузится и все методы доступны и работают нормально. А ошибка таже - -2147023149 ? Для Win200 - Посмотри содержимое журнала системы и приложений в просмотре событий. Скорее всего что-то там будет связанное с твоими серверами.
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #15 : 19-12-2003 09:41 » |
|
Сделал тестовый клиент и сервер. Удалось даже воспроизвести точно такую же ошибку. Пофиксил. Работает под w2k & win98. Привожу куски кода. :arrow: Для сервера: В функцию _tWinMain где-то после строки _Module.dwThreadID = GetCurrentThreadId(); надо вставить 1. CSecurityDescriptor sd; sd.InitializeFromThreadToken(); hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); _ASSERTE(SUCCEEDED(hr));
На доступ будут только влиять атрибуты защиты запуска(из dcomcnfg), однако это не работает с точками подключени для win98. 2. полностью никакой защиты hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL); ATLASSERT(SUCCEEDED(hr));
Это тоже не работает с точками подключени для win98. Выход такой - На сервере(в дополнении к любому из вышеперечисленных способах) в функциях Advise и всех Fire_EventX вызывать такую штуку(снятие защиты для прокси клиентского объекта) CoSetProxyBlanket(pUnkSink, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
В Advise пишется после GetConnectionInterface(&iid), а в Fire_EventX перед pDispatch->Invoke. :arrow: На клиенте(после CoInitialize) CSecurityDescriptor sd; sd.InitializeFromThreadToken(); hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL)); _ASSERTE(SUCCEEDED(hr));
|
|
« Последнее редактирование: 23-11-2007 15:45 от Алексей1153++ »
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #16 : 19-12-2003 09:41 » |
|
NetRaider, даже тяжело представить сейчас мое счастье! Оно заработало!!!! От это где я стормозила!!!! Все было тупо до беспредела! Поставила доступ кому надо на запуск СОМ+. И все заработало сразу же!!!! А я уже столько методов испробовала подключения к событиям!!!! Фантастика!!! Всем огромное СПАСИБО!!! NetRaider, тебе в особенности!
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #17 : 19-12-2003 09:43 » |
|
NetRaider, даже тяжело представить сейчас мое счастье! Оно заработало!!!! От это где я стормозила!!!! Все было тупо до беспредела! Поставила доступ кому надо на запуск СОМ+. И все заработало сразу же!!!! А я уже столько методов испробовала подключения к событиям!!!! Фантастика!!! Всем огромное СПАСИБО!!!NetRaider, тебе в особенности!
Обращайтесь еще (только вот не верется мне, что под win98 работает...)
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #18 : 19-12-2003 10:38 » |
|
Как это ни подлюшно, но оно под 98-й действительно не работает 8(. Так просто дело не закончилось... А че еще мона сделать , чтобы и так работало? Надо ведь именно под 98-ю. С ХР проблем вроде как нет. Проляпала я сообщение с кодом, сейчас так попробую. Только еще один вопрос на счет вставки в Адвайз.. Мне его в своем клиенте реализовать или мона лихо в атлевских файлах между дефайнами вставить?
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #19 : 19-12-2003 11:07 » |
|
Попробовала я у клиента свой адвайз реализовать, так вот вываливается все на FindConnectionPoint (-2147220992). Или я не так что-то делаю, или еще не все с настройками. Если не жалко, можешь мне своего всего адвайза кинуть?
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #20 : 20-12-2003 05:59 » |
|
Если не жалко, можешь мне своего всего адвайза кинуть?
Держи... template <class T> class CProxy_ISampleObjectWithEventsEvents : public IConnectionPointImpl<T, &DIID__ISampleObjectWithEventsEvents, CComDynamicUnkArray> { //Warning this class may be recreated by the wizard.
public:
STDMETHODIMP Advise(IUnknown* pUnkSink, DWORD* pdwCookie) { T* pT = static_cast<T*>(this); IUnknown* p; HRESULT hRes = S_OK; if (pUnkSink == NULL || pdwCookie == NULL) return E_POINTER; IID iid; GetConnectionInterface(&iid); CoSetProxyBlanket(pUnkSink, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE); hRes = pUnkSink->QueryInterface(iid, (void**)&p); if (SUCCEEDED(hRes)) { pT->Lock(); *pdwCookie = m_vec.Add(p); hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT; pT->Unlock(); if (hRes != S_OK) p->Release(); } else if (hRes == E_NOINTERFACE) hRes = CONNECT_E_CANNOTCONNECT; if (FAILED(hRes)) *pdwCookie = 0; return hRes; }
HRESULT Fire_Event1(BSTR str) { CComVariant varResult; T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant pvars[1]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { VariantClear(&varResult); pvars[0] = str; DISPPARAMS disp = { pvars, NULL, 1, 0 };
CoSetProxyBlanket(pDispatch, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
HRESULT hr = pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL); if(FAILED(hr)) if(DISP_E_EXCEPTION != hr) { // Это исправление бага ATL-визарда. // Без этого исправления ошибки при обратных вызовах // попросту игнорируются varResult.scode = hr; break; } } } return varResult.scode; } HRESULT Fire_Event2() { CComVariant varResult; T* pT = static_cast<T*>(this); int nConnectionIndex; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { varResult.Clear(); DISPPARAMS disp = | NULL, NULL, 0, 0 };
CoSetProxyBlanket(pDispatch, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
HRESULT hr = pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL); if(FAILED(hr)) if(DISP_E_EXCEPTION != hr) { varResult.scode = hr; break; } } } return varResult.scode; } };
И idl для сервера на всяк случай: import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(70895D9F-00F3-11D6-8EE6-00C0DF039163), dual, helpstring("ISampleObjectWithEvents Interface"), pointer_default(unique) ] interface ISampleObjectWithEvents : IDispatch { [id(1), helpstring("method Method1")] HRESULT Method1([in] BSTR str); };
[ uuid(70895D93-00F3-11D6-8EE6-00C0DF039163), version(1.0), helpstring("SampleServerWithEvents 1.0 Type Library") ] library SAMPLESERVERWITHEVENTSLib { importlib("stdole32.tlb"); importlib("stdole2.tlb");
[ uuid(70895DA1-00F3-11D6-8EE6-00C0DF039163), helpstring("_ISampleObjectWithEventsEvents Interface") ] dispinterface _ISampleObjectWithEventsEvents { properties: methods: [id(1), helpstring("method Event1")] HRESULT Event1([in] BSTR str); [id(2), helpstring("method Event2")] HRESULT Event2(); [id(3), helpstring("method Event3")] void Event3(); };
[ uuid(70895DA0-00F3-11D6-8EE6-00C0DF039163), helpstring("SampleObjectWithEvents Class") ] coclass SampleObjectWithEvents { [default] interface ISampleObjectWithEvents; [default, source] dispinterface _ISampleObjectWithEventsEvents; }; };
|
|
« Последнее редактирование: 23-11-2007 15:48 от Алексей1153++ »
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #21 : 20-12-2003 08:31 » |
|
NetRaider, доброе утро! Очень доброе утро! А теперь признавайся, сколько я тебе пива должна . Потому что теперь эта система работает и под 98-й виндой и даже там, где DCOM не стоит!!!! Я наверное все-таки буду жить !!! Уря!! Шоб я без тебя делала. Надеюсь, что это окончательный вариант. Супер!
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #22 : 20-12-2003 08:44 » |
|
NetRaider, доброе утро! Очень доброе утро! А теперь признавайся, сколько я тебе пива должна . Потому что теперь эта система работает и под 98-й виндой и даже там, где DCOM не стоит!!!! Я наверное все-таки буду жить !!! Уря!! Шоб я без тебя делала. Надеюсь, что это окончательный вариант. Супер! Я рад, что все получилось. А пиво я люблю 8) ... Заходи еще.
|
|
|
Записан
|
|
|
|
FantomCat
Гость
|
|
« Ответ #23 : 20-12-2003 08:55 » |
|
А я рада еще больше! Зайду как только , так и сразу! Я пиво тоже люблю, жалко только что его на форуме никак вместе не попьешь
|
|
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #24 : 20-12-2003 09:03 » |
|
А я рада еще больше! Зайду как только , так и сразу! Я пиво тоже люблю, жалко только что его на форуме никак вместе не попьешь Да уж... То что на форуме нельзя пить пиво - является единственным его недостатком. Надо Грому сказать - мож исправит
|
|
|
Записан
|
|
|
|
|
|