Пожалуйста, помогите решить проблему.
Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!
...А отсюда наливаем, когда рецепт написан совсем неразборчиво...
Здравствуйте Михаил, Вы писали:
М>Пожалуйста, помогите решить проблему. М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!
Так как есть Custom Marshaling, то в общем случае это задача точно не решается. И даже в частном случае — стандартный маршалин, Windows тебе скорее всего не даст этой инфо, это исключительно внутренее, и повода этo показывать нет, а то народ начнет извращаться — как ты это хочешь сделать :))
Если тебе надо выяснить умер ли объект, то надо его пинговать, и при этом IUnknown для этого не подходит, так как он может быть оптимизирован маршалерром и работать даже когда связи с объектом нет. Так что надо какой-то более конкретный интерфейс, со специальным методом, который ничего не делает, и просто проверяет соединение. При это важно уметь прерывать этот вызов, так как иначе он может висеть до бесконечности — я тестировал, весит.
Я раньше дискутировал проблему прерывания, основными результами было:
— посмотреть http://www.optim.ru/cs/2000/4/com_htm/com_2.asp
— использовать IMessageFileter::MessagePending, если это STA (Single Thread Apartment), или
— использовать CoCancelCall (это работает для любой модели апартмента), и при этом если ты программируешь под Windows 2000, чтобы не создавать дополнительных ниток можно использовать Waitable Timer (см. ::CreateWaitableTimer)
И если ты не хочешь последовательно проверять все объекты, то надо создать кучу ниток для проверки их параллельно — так должно быть намного эффективнее, особенно если речь идет о сетевых соединениях.
Здравствуйте ZORK, Вы писали:
ZORK>И если ты не хочешь последовательно проверять все объекты, то надо создать кучу ниток для проверки их параллельно — так должно быть намного эффективнее, особенно если речь идет о сетевых соединениях.
Я и остановился на этом варианте. Но требуется — всего лишь определить модуль-источник интерфейса! Если это играет роль, уточню задачу. Надо из списка активных объектов т.е. ROT выбрать нужные, и все. Те которые нужны — file moniker'ы (остальные легко отсеиваются по IMoniker->IsSystemMoniker), но не все, а рожденные нужным приложением. Причем имя файла может быть любым, естественно. Парсить имя файла — не годится. Поскольку не определено, какие юзер хочет имена. Какие хочет, такие и будут. Например, юзер может захотеть, чтобы xren.xls был Word'овским документом. В заключение добавлю, что эта операция висит в обновлении окна диалога, т.е. ждать ну совсем не хочется. И задача — _быстро_ узнать, чьи моникеры в ROT. Без опроса их самих. И в общем случае их там может быть много. По-моему, задача типа построения списка открытых (во многих окнах) документов имеет нормальное решение?
...А отсюда наливаем, когда рецепт написан совсем неразборчиво...
Здравствуйте VladD2, Вы писали:
VD>Здравствуйте ZORK, Вы писали:
VD>Zork! Отличное знание COM-а. Особенно для человека пытающегося развизать религиозную войну Java vs MS. :)
:)) — ну если ты обратишь внимание на мой ответ, то там был концептуальный анализ. Суть которого сводилась: если вы работает с объектами, то и работайте с объектами ...и не надо вдруг вспоминать про то как они устроенны и где лежает. Это кстати называется инкопсуляцией. Потому что если Вы так будет делать, то скорее всего работать у вас это будет как С# Beta 1 — только на компьютере, на котором это было написанно :))
А религиозной войны — поверь, я тут не развожу. А мне зачем?
Здравствуйте Михаил, Вы писали:
М>Пожалуйста, помогите решить проблему. М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!
Ничего если я вклюнюсь.
Решил посмотреть на ROT в Win 2000.
Вызвал EnumRunning
А в ответ получил для номера элемента (Celt) = 1 Oбъект, а при
попытке получить любой другой объект из списка сообщение об ошибке.
CoInitialize(NULL);
res = GetRunningObjectTable (0, &pROT);
res = pROT->EnumRunning(&pEM); // здесь приходит сообщение о том,
// что была ошибка доступа к файлу
// но не фатальная, все продолжает
// работать
for (int i=0; i<10; i++)
{
res = pEM->Next(i, (IMoniker**)&pMon, &iMonCount); pMon->... // что нибудь делаем
} pEM->Release(); pROT->Release();
CoUninitialize();
Здравствуйте Михаил, Вы писали:
М>Пожалуйста, помогите решить проблему. М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит
Здравствуйте Snax, Вы писали:
S>Здравствуйте Михаил, Вы писали:
М>>Пожалуйста, помогите решить проблему. М>>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит
В догонку. Для proxy/stub получишь конечно HMODULE этих proxy/stub. Тогда его нужно маршалить в поток с флагом "другой компрьютер"
и смотреть что внутри. Внутри будет имя машины, ID процесса и ID апартмента и cookie, с которого там можно получить IUnknown.
Так что вычислить имя .exe зная имя тачки и ID процесса можно, но если интерфейс лежит в Dll то фиг. Теоретически, если компьютер
тот же самый, можно закинуть в тот процесс свою DLL и если объект с FTM или MTA-шный, можно узнать "родной" HMODULE. Если объект STA-шный
можно попробовать из нашей ловкой DLL создать еще более ловкий STA-объект и он с большой вероятностью попадет в тот же STA. Хотя
может и не попасть. Такие пироги.
Здравствуйте Михаил, Вы писали:
М>Пожалуйста, помогите решить проблему. М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!
-----------------------------------------
Если имет дело с ActiveX объектами, то они дожны реализовывать IOleObject поидее.
Этот код позволяет узнать какие еще есть элементы на форме, по идее, то же самое и
с ROT