У меня есть 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:
- MyService.exe устанавливается с помощью командной строки / Service:
MyServiceTest.exe вызывает CoCreateInstance, а MyService WinMain вызывается. Затем вызывается CAtlServiceModuleT :: Start, который определяет, что исполняемый файл был запущен с параметром командной строки '-Embedding'. Он определяет, что он установлен как служба и как таковой вызывает :: StartServiceCtrlDispatcher (). Этот вызов не выполняется с кодом ошибки 1063 (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT). По МС:
"Эта ошибка возвращается, если программа запускается как консольное приложение, а не как служба. Если программа будет запускаться как консольное приложение для целей отладки, структурируйте ее так, чтобы специфичный для службы код не вызывался при эта ошибка возвращается. "
Ошибка вызова, MyService.exe завершается, а время ожидания вызова CoCreateInstance истекает.
MyService.exe НЕ установлен в качестве службы, но зарегистрирован через / RegServer
MyServiceTest.exe вызывает CoCreateInstance, а MyService WinMain вызывается. MyService.exe создается под зарегистрированной учетной записью пользователя (не LOCALSYSTEM). Исполняемый файл успешно запускается, но не как служба, что не является желаемым поведением. Несмотря на то, что не работает как служба, вызов CoCreateInstance () завершается успешно, и я получаю действительный указатель интерфейса, через который я могу вызывать функции MyService COM.
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. Это желаемое поведение (для службы, которая должна работать).