Доступ к COM-объекту, который в виде сервиса
От: Аноним  
Дата: 30.05.10 10:29
Оценка:
Привет.

Можно ли как-то получить COM-объект, который находится в рамках приложения, запущенного как сервис? Почему-то CreateInstance() пытается создать еще один экземпляр приложения.

Заранее спасибо.
com service
Re: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 30.05.10 14:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет.


А>Можно ли как-то получить COM-объект, который находится в рамках приложения, запущенного как сервис? Почему-то CreateInstance() пытается создать еще один экземпляр приложения.


А>Заранее спасибо.


Зарегистрировать его в ROT через IRunningObjectTable.Register с флагом ROTFLAGS_ALLOWANYCLIENT. Получать можно как через этот интерфейс, так и хелпером GetActiveObject.
"Нормальные герои всегда идут в обход!"
Re[2]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 30.05.10 14:40
Оценка:
Здравствуйте, Аноним, Вы писали:

http://support.microsoft.com/kb/156673
"Нормальные герои всегда идут в обход!"
Re[3]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 31.05.10 14:03
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Аноним, Вы писали:


JR>http://support.microsoft.com/kb/156673


Да, действительно, помогло зарегистрировать объект в ROT. Получаю в другом модуле его из того же самого IRegisterObjectTable. С помощью GetObject(), задав IMoniker правильный.

Однако возникла следующая проблема: сам мой объект внутри себя тоже содержит COM-объекты (вектор). Раньше, получив основной, можно было вызывать его метод Get() и получать "внутренности". (Без абстракций: основной класс — IDataServer, внутренности — IDSTable (их несколько)). Сейчас же, если так делать, указатель на IDSTable инициализируется, но при любом обращении к нему вылезает COM Exception 800706F4. Что делать в такой ситуации? Тоже каждый IDSTable регистрировать в ROT?
Re[4]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 31.05.10 15:25
Оценка:
Здравствуйте, spy__, Вы писали:

__> Тоже каждый IDSTable регистрировать в ROT?


Да нет, и так должно работать. Вообще регистрировать в ROT рутовый объект — самый простой путь, однако можно обойтись и без такой регистрации, просто это расписывать несколько дольше. Вообще-то я думал, что по приведённой ссылке рассмотрены оба варианта, нет? Значит, я просто забыл. Но где-то там рядом должен быть и пример работы с сервисом без ROT, если конечно память мне опять не изменяет

COM Exception 800706F4 — это RPC_X_NULL_REF_POINTER, и насколько мне известно, генерится оно заглушкой, когда Вы передаёте каким-то параметром NULL, а заглушка ожидает в нём валидный указатель. В эту сторону надо копать.

__>Раньше, получив основной, можно было вызывать его метод

А это "раньше" он у Вас не инпроцессным сервером, часом, был?
"Нормальные герои всегда идут в обход!"
Re: Доступ к COM-объекту, который в виде сервиса
От: michae1  
Дата: 04.06.10 08:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет.


А>Можно ли как-то получить COM-объект, который находится в рамках приложения, запущенного как сервис? Почему-то CreateInstance() пытается создать еще один экземпляр приложения.


А>Заранее спасибо.


Привет,
как уже писали можно использовать ROT, можно прописать макрос DECLARE_CLASSFACTORY_SINGLETON в классе com-объекта и использовать обычный CoCreateInstance. В случае если ты создаешь com-объект в сервисе необходимо предварительно сделать вызов ф-ции CoInitializeSecurity, чтобы разрешить доступ к объекту.
Re[5]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 09.06.10 10:22
Оценка:
С регистрацией в ROT я разобрался. Единственный момент, который не работает (и в данный момент очень важен) — это проблема с Win 2003 Server. Ошибка 0x80004015. В интернетах пишут про CoInitializeSecurity(), но я пока не нашел объяснения доступным языком. Пробовал вызывать функцию из моего сервиса:

HRESULT coRes = CoInitializeSecurity( NULL,
        -1, 
        NULL, 
        NULL, 
        RPC_C_AUTHN_LEVEL_PKT, 
        RPC_C_IMP_LEVEL_IMPERSONATE, 
        NULL, 
        EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, 
        NULL );


Резльтат S_OK, но регистрация все равно не проходит. Что я делаю не так?

Заранее спасибо.
Re[6]: Доступ к COM-объекту, который в виде сервиса
От: michae1  
Дата: 09.06.10 10:52
Оценка:
Здравствуйте, spy__, Вы писали:

__>С регистрацией в ROT я разобрался. Единственный момент, который не работает (и в данный момент очень важен) — это проблема с Win 2003 Server. Ошибка 0x80004015. В интернетах пишут про CoInitializeSecurity(), но я пока не нашел объяснения доступным языком. Пробовал вызывать функцию из моего сервиса:


__>
__>HRESULT coRes = CoInitializeSecurity( NULL,
__>        -1, 
__>        NULL, 
__>        NULL, 
__>        RPC_C_AUTHN_LEVEL_PKT, 
__>        RPC_C_IMP_LEVEL_IMPERSONATE, 
__>        NULL, 
__>        EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, 
__>        NULL ); 
__>


__>Резльтат S_OK, но регистрация все равно не проходит. Что я делаю не так?


__>Заранее спасибо.


Возможно поможет это: здесь,
обсуждалось здесь
Re[7]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 09.06.10 11:59
Оценка:
Здравствуйте, michae1, Вы писали:

M>Здравствуйте, spy__, Вы писали:


__>>С регистрацией в ROT я разобрался. Единственный момент, который не работает (и в данный момент очень важен) — это проблема с Win 2003 Server. Ошибка 0x80004015. В интернетах пишут про CoInitializeSecurity(), но я пока не нашел объяснения доступным языком. Пробовал вызывать функцию из моего сервиса:


__>>
__>>HRESULT coRes = CoInitializeSecurity( NULL,
__>>        -1, 
__>>        NULL, 
__>>        NULL, 
__>>        RPC_C_AUTHN_LEVEL_PKT, 
__>>        RPC_C_IMP_LEVEL_IMPERSONATE, 
__>>        NULL, 
__>>        EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, 
__>>        NULL ); 
__>>


__>>Резльтат S_OK, но регистрация все равно не проходит. Что я делаю не так?


__>>Заранее спасибо.


M>Возможно поможет это: здесь,

M>обсуждалось здесь


Само приложение у меня (которое объект содержит регистрируемый в ROT) работает не как сервис. Его запускает другое, которое является сервисом. То есть мое висит в процессах, но в сервисах его нет.
Re[8]: Доступ к COM-объекту, который в виде сервиса
От: michae1  
Дата: 09.06.10 13:52
Оценка:
Здравствуйте, spy__, Вы писали:

skip

__>Само приложение у меня (которое объект содержит регистрируемый в ROT) работает не как сервис. Его запускает другое, которое является сервисом. То есть мое висит в процессах, но в сервисах его нет.


Это не важно, если сервис у тебя запущен под Local Service, то процесс который будет порожден тоже будет под этим аккаунтом. Если не ошибаюсь при работе с ROT учитывается не только IL, но и аккаунт под которым объект был добавлен.
Попробуй забить на ROT и работать через CreateInstance и макрос DECLARE_CLASSFACTORY_SINGLETON (если архитектура позволят) так как я описал ниже. У меня под 7 такая схема успешно работает.

P.S. Если не поможет, напиши больше информации об архитектуре приложения: что, откуда и зачем вызывается? а то трудно понять в чем беда
Re[6]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 09.06.10 15:52
Оценка:
Здравствуйте, spy__, Вы писали:

__>С регистрацией в ROT я разобрался.


А что было-то?

__>Единственный момент, который не работает (и в данный момент очень важен) — это проблема с Win 2003 Server. Ошибка 0x80004015.


CoInitializeSecurity Вам не поможет, она не влияет на RunAs, а именно её Вам надо настроить, плюс раздать права на работу с сервером нужным пользователям. Но в такой конфигурации, как Вы описали

Само приложение у меня (которое объект содержит регистрируемый в ROT) работает не как сервис. Его запускает другое, которое является сервисом.


даже затрудняюсь сказать, как настраивать По идее, нужно указать в RunAs пользователя, под которым будет работать Ваше приложение. Но в Вашем случае это LocalSystem, а его можно указать только для COM-серверов в виде сервиса. Вам обязательно работать под LocalSystem? Может подойдёт специально созданный пользователь, пол него и настроить защиту сервера? Правда, возни и в этом случае будет прилично, если не подходит запуск службы под ним-же — придётся программно давать ему доступ к станции и десктопу службы, да и другие грабли возможны.
"Нормальные герои всегда идут в обход!"
Re[7]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 15.06.10 07:26
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, spy__, Вы писали:


__>>С регистрацией в ROT я разобрался.


JR>А что было-то?


__>>Единственный момент, который не работает (и в данный момент очень важен) — это проблема с Win 2003 Server. Ошибка 0x80004015.


JR>CoInitializeSecurity Вам не поможет, она не влияет на RunAs, а именно её Вам надо настроить, плюс раздать права на работу с сервером нужным пользователям. Но в такой конфигурации, как Вы описали


JR>

JR>Само приложение у меня (которое объект содержит регистрируемый в ROT) работает не как сервис. Его запускает другое, которое является сервисом.


JR> даже затрудняюсь сказать, как настраивать По идее, нужно указать в RunAs пользователя, под которым будет работать Ваше приложение. Но в Вашем случае это LocalSystem, а его можно указать только для COM-серверов в виде сервиса. Вам обязательно работать под LocalSystem? Может подойдёт специально созданный пользователь, пол него и настроить защиту сервера? Правда, возни и в этом случае будет прилично, если не подходит запуск службы под ним-же — придётся программно давать ему доступ к станции и десктопу службы, да и другие грабли возможны.


Я пока раскопал, что сервисы запускаются в 0 сессии. Соответственно, мой сервис все стартует также в 0 сессии. Но задача еще в том, чтобы можно было обращаться к объекту из других сессий. На Windows Vista у меня нет проблем с подменой Session ID процессу: все гладко и ровно, стартуются все процессы там где надо. На 2003 винде в процессах показывается мой, и даже сессия у него отображена та, которую я настраиваю, но остальное ничего не работает. Он как будто suspend. Короче, лажа какая-то с этой виндой. Ничерта там не работает.
Re[8]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 15.06.10 09:47
Оценка:
Здравствуйте, spy__, Вы писали:

Разница между Vista и предыдущими версиями по части сессий в том, что на Vista нулевая сессия выделена исключительно под сервисы, а ранее она-же была и первой интерактивной. Но сессия — это только верхний, так сказать, уровень. Кроме них есть ещё Window stations, которые отдельно для интерактивного юзера, отдельно для служб, причём для служб их стандартно обычно несколько. Плюс ещё один "водораздел" системы безопасности — связанные со станциями desktops, к которым подключаются потоки. И эти десктопы влияют на, например, пхождение сообщений окнам. Ваши проблемы кроются, видимо, где-то в этих областях, но "ничего не работает" — это слишком расплывчато, да и "удалённая отладка" через форум вряд-ли будет эффективна. Стоит попытаться зацепиться за какую-то конкретную проблему и размотать до конца. Удачи
"Нормальные герои всегда идут в обход!"
Re: Доступ к COM-объекту, который в виде сервиса
От: PanychY  
Дата: 15.06.10 10:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет.

А>Можно ли как-то получить COM-объект, который находится в рамках приложения, запущенного как сервис? Почему-то CreateInstance() пытается создать еще один экземпляр приложения.
А>Заранее спасибо.
Возможно я не правильно понял...
CoRegisterClassObject(...,...,...,REGCLS_MULTIPLEUSE,...)
Тогда DCOM буде вынужден обращаться к единственному экземпляру... по крайней мере у меня так работает.
Re[9]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 15.06.10 11:30
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, spy__, Вы писали:


JR>Разница между Vista и предыдущими версиями по части сессий в том, что на Vista нулевая сессия выделена исключительно под сервисы, а ранее она-же была и первой интерактивной. Но сессия — это только верхний, так сказать, уровень. Кроме них есть ещё Window stations, которые отдельно для интерактивного юзера, отдельно для служб, причём для служб их стандартно обычно несколько. Плюс ещё один "водораздел" системы безопасности — связанные со станциями desktops, к которым подключаются потоки. И эти десктопы влияют на, например, пхождение сообщений окнам. Ваши проблемы кроются, видимо, где-то в этих областях, но "ничего не работает" — это слишком расплывчато, да и "удалённая отладка" через форум вряд-ли будет эффективна. Стоит попытаться зацепиться за какую-то конкретную проблему и размотать до конца. Удачи


Да, я понимаю, что в телепата играть очень трудно.

Внесу более конкретное желание: ищу пример, в котором есть сервер COM в виде сервиса, но внутри не простой объект крутится, а составной (например, содержит вложенный мембер, который является COM-объектом). И этот мембер как-то вытаскивается клиентом.

Мои попытки пока не увенчались успехом.

Такое вот

STDMETHODIMP CHelloWorld::GetTestCase(ITestCase **tc)
{
    if (!m_TestCase)
        m_TestCase.CoCreateInstance(__uuidof(TestCase));
    *tc = m_TestCase;
    return S_OK;
}


не работает. Возвращается убогий интерфейс.

А такое нормально отрабатывает (переброс тупой строки переданной назад):

STDMETHODIMP CHelloWorld::SayOloloWrapper(unsigned char *in, unsigned char *out)
{
    return m_TestCase->SayOlolo(in, out);
}


Метод сам прост:

STDMETHODIMP CTestCase::SayOlolo(unsigned char *in, unsigned char *out)
{
    *out = *in;
    return S_OK;
}


Класс пытаюсь вернуть так:

STDMETHODIMP CHelloWorld::GetTestCase(ITestCase **tc)
{
    if (!m_TestCase)
        m_TestCase.CoCreateInstance(__uuidof(TestCase));
    *tc = m_TestCase;
    return S_OK;
}
Re[10]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 15.06.10 14:40
Оценка:
Здравствуйте, spy__, Вы писали:

__>Такое вот


__>
__>STDMETHODIMP CHelloWorld::GetTestCase(ITestCase **tc)
__>{
__>    if (!m_TestCase)
__>        m_TestCase.CoCreateInstance(__uuidof(TestCase));
__>    *tc = m_TestCase;
__>    return S_OK;
__>}
__>


__>не работает. Возвращается убогий интерфейс.


Что значит "убогий"? Мёртвая ссылка? Может просто нужен AddRef?

Писать пример с нуля лениво, вот здесь давно уже валяется пример COM-сервера в службе. Файл comservice2.zip, правда на Delphi. Я добавил в него ещё один объект с интерфейсом, добавил интерфейс с методом, возвращающем этот объект. Реализовал этот интерфейс в тамошних объектах, проверил — всё работает Система WinXP SP3.
Правда, с регистрацией этого добавленного объекта возиться не стал, потому в методе создавал его напрямую, а не через CoCreateInstance, но это вряд-ли могло повлиять — настройки защиты применяются на уровне приложения.
"Нормальные герои всегда идут в обход!"
Re[10]: Доступ к COM-объекту, который в виде сервиса
От: Jolly Roger  
Дата: 15.06.10 14:42
Оценка:
Здравствуйте, spy__, Вы писали:

Ешё момент, а маршалер для этого ITestCase есть?
"Нормальные герои всегда идут в обход!"
Re[11]: Доступ к COM-объекту, который в виде сервиса
От: spy__  
Дата: 21.06.10 14:07
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, spy__, Вы писали:


JR>Ешё момент, а маршалер для этого ITestCase есть?


Да, там все есть. Я накосячил немного в другом месте из-за невнимательности. Совсем глупо, не создавал объект, а юзал его.

Скачал какой-то пример с codeproject'а, написал к нему, проверил на 2003 винде — все ОК. Правда, сейчас я ловлю access violation, когда пробую обращаться к методам COM-объекта из разных участков приложения. Поток один и тотже. Ковыряюсь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.