CoCreateInstance не запускается и не подключается к службе ATL COM - PullRequest
2 голосов
/ 28 апреля 2011

У меня есть exe-служба ATL COM (MyService.exe), которая компилируется и работает нормально. Если я устанавливаю этот сервис (через MyService.exe / Service), он успешно устанавливается в SCM. Я могу запустить службу через SCM, и она работает нормально, под учетной записью LOCALSYSTEM.

Моя проблема возникает, когда я пытаюсь создать экземпляр класса COM, определенного службой. Моё приложение для тестирования (MyServiceTest.exe) вызывает следующее:

::CoInitialize(NULL);
::CoInitializeSecurity(NULL, 
                        NULL, 
                        NULL, 
                        NULL, 
                        RPC_C_AUTHN_LEVEL_PKT, 
                        RPC_C_IMP_LEVEL_IMPERSONATE, 
                        NULL, 
                        EOAC_NONE, 
                        NULL);
ATL::CComPtr<IMyServiceInterface> pInterface;
HRESULT hr = CoCreateInstance(CLSID_MyServiceInterface, NULL, CLSCTX_LOCAL_SERVER, IID_IMyServiceInterface, reinterpret_cast<void**>(&pInterface));

При вызове CoCreateInstance происходит несколько разных вещей, в зависимости от того, как установлен MyService.exe:

  1. MyService.exe устанавливается с помощью командной строки / Service:
    MyServiceTest.exe вызывает CoCreateInstance, а MyService WinMain вызывается. Затем вызывается CAtlServiceModuleT :: Start, который определяет, что исполняемый файл был запущен с параметром командной строки '-Embedding'. Он определяет, что он установлен как служба и как таковой вызывает :: StartServiceCtrlDispatcher (). Этот вызов не выполняется с кодом ошибки 1063 (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT). По МС:

"Эта ошибка возвращается, если программа запускается как консольное приложение, а не как служба. Если программа будет запускаться как консольное приложение для целей отладки, структурируйте ее так, чтобы специфичный для службы код не вызывался при эта ошибка возвращается. "

Ошибка вызова, MyService.exe завершается, а время ожидания вызова CoCreateInstance истекает.

  1. MyService.exe НЕ установлен в качестве службы, но зарегистрирован через / RegServer
    MyServiceTest.exe вызывает CoCreateInstance, а MyService WinMain вызывается. MyService.exe создается под зарегистрированной учетной записью пользователя (не LOCALSYSTEM). Исполняемый файл успешно запускается, но не как служба, что не является желаемым поведением. Несмотря на то, что не работает как служба, вызов CoCreateInstance () завершается успешно, и я получаю действительный указатель интерфейса, через который я могу вызывать функции MyService COM.

  2. MyService.exe НЕ установлен в качестве службы, зарегистрирован через / RegServer и уже работает (например, после успешного запуска в сценарии 2)
    MyServiceTest.exe вызывает CoCreateInstance, и создается экземпляр НОВОГО экземпляра MyService.exe снова под зарегистрированной учетной записью пользователя. Это поведение продолжается для каждого последующего вызова CoCreateInstance.

Мое желаемое поведение - я могу установить MyService.exe как службу, и CoCreateInstance запустит сервер или подключится к текущему экземпляру MyService.exe, если служба уже запущена. Насколько я знал, приведенный выше код должен вести себя так. Чего мне не хватает?

Кажется, тот факт, что служба работает в режиме LOCALSYSTEM, в то время как простая альтернатива RegServer работает под локальным пользователем, может быть уместной, но я не уверен, что это проблема.

Служебный вызов CoInitializeSecurity:

HRESULT hr = CoInitializeSecurity(0,
                                    -1,
                                    0,
                                    0,
                                    RPC_C_AUTHN_LEVEL_PKT,
                                    RPC_C_IMP_LEVEL_IMPERSONATE,
                                    0,
                                    EOAC_NONE,
                                    0);

Что я делаю не так?

P.S. MyService.exe не должен завершаться после запуска, так как он содержит функцию WaitForSingleObject () в функции Run (), которая ожидает внешнего сигнала (который также установлен в OnStop (), так что SCM может остановить службу). Вот почему MyService.exe сохраняется после завершения MyServiceTest.exe. Это желаемое поведение (для службы, которая должна работать).

Ответы [ 2 ]

1 голос
/ 02 мая 2011

Оказывается, виновником было то, как служба была зарегистрирована. Чтобы класс запустил свое управляющее приложение как службу, управляющему приложению необходимо добавить записи в реестр, чтобы он распознавался как локальный сервер, т. Е.

(MyService.rgs)

HKCR
{
    NoRemove AppID
    {
        ForceRemove {6E5B1E7E-3340-4553-A356-76F1C3543452} = s 'MyService'
        {
            val LocalService = s 'MyService'
            val ServiceParameters = s '-Service'
        }

        'MyService.EXE'
        {
            val AppID = s {6E5B1E7E-3340-4553-A356-76F1C3543452}
        }
    }
}

AppID которого указан в MyService.rgs.

Это приводит к следующему расположению в реестре:

HKCR
    AppID
        {6E5B1E7E-3340-4553-A356-76F1C3543452} (Contains LocalService, ServiceParameters REG_SZ's)
        MyService.EXE (Contains AppID REG_SZ)
    CLSID
        {MyServiceInterface GUID} (Contains MyService.EXE AppID)

Соответствующие ссылки:
Значение LocalService
Перегрузка LocalServer32 в CLSID CoClass
Указание AppID для CLSID

1 голос
/ 28 апреля 2011

Простите, если вы уже рассмотрели это:

Запустите DCOMCNFG.EXE.

Детализация через Службы компонентов \ Компьютеры \ Мой компьютер \ Конфигурация DCOM.

Найдите свой компонент, щелкните правой кнопкой мыши и активируйте «Свойства».

На вкладке «Удостоверение» убедитесь, что компонент COM настроен для работы под тем же удостоверением, под которым работает служба.

...