#c #winapi
#c #winapi
Вопрос:
Всякий раз, когда я пытаюсь остановить свою службу через диспетчер служб, я получаю следующую ошибку, и служба остается в запущенном состоянии. «Не удалось остановить службу на локальном компьютере. Служба не вернула ошибку. Это может быть внутренняя ошибка Windows или ошибка внутренней службы «. У меня были такие проблемы с этой проблемой, что я старался следовать логике Microsoft как можно лучше. http://msdn.microsoft.com/en-us/library/windows/desktop/bb540474 (v = vs.85).aspx С этим связана аналогичная проблема в .Net 1.1, которую вы найдете, если выполните поиск; однако я вообще не использую framweork.
void WINAPI serviceCtrlHandler(DWORD dwCtrl )
{
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
SetEvent(stopEvent);
ReportSvcStatus(serviceStatus->dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
void WINAPI startMain(DWORD argc, LPTSTR *argv)
{
serviceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler);
serviceStatus->dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus->dwServiceSpecificExitCode = NO_ERROR;
if (serviceStatusHandle == 0)
{
debug->DebugMessage(L"RegisterServiceCtrlHandler() failed, error: " Error::GetErrorMessageW(GetLastError()));
return;
}
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
if (!SetServiceStatus(serviceStatusHandle, serviceStatus))
{
//debug->DebugMessage(L"SetserviceStatus() failed, error: " Error::GetErrorMessageW(GetLastError()));
//return;
}
stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
boost::thread dust_main_thread(dust_main);
while(1)
{
WaitForSingleObject(stopEvent, INFINITE);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
}
VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
serviceStatus->dwCurrentState = dwCurrentState;
serviceStatus->dwWin32ExitCode = dwWin32ExitCode;
serviceStatus->dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus->dwControlsAccepted = 0;
else serviceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
serviceStatus->dwCheckPoint = 0;
else
serviceStatus->dwCheckPoint = dwCheckPoint ;
SetServiceStatus(serviceStatusHandle, serviceStatus);
}
Комментарии:
1. Что делает boost::thread dust_main_thread(dust_main); делать? Он зацикливается или порождает другой поток?
2. Он ожидает подключения к каналу и обрабатывает запросы. В любом случае, я должен быть в состоянии удалить эту строку оттуда, и она должна просто ждать события остановки вечно.
3. Я предполагаю, что переменная serviceStatus является глобальной, поскольку я не вижу, чтобы она была объявлена. Следующая строка после вашего SetEvent — сообщить значение serviceStatus->dwCurrentState . Однако, поскольку порядок выполнения после SetEvent не гарантируется, возможно, вы могли бы снова сообщить SERVICE_STOPPED, а затем SERVICE_STOPPED_PENDING в зависимости от того, где был переключен контекст потока.
4. На самом деле это должно быть гарантировано до тех пор, пока событие запускается в том же потоке.
5. Проблема заключалась в ошибке с моей стороны. Удаленная отладка устранила эту проблему для меня. Проблема заключалась в том, что когда моя служба завершалась естественным образом, она вызывала serviceCtrlHandler(SERVICE_STOP); который должен быть serviceCtrlHandler(SERVICE_CONTROL_STOP); Это привело к завершению программы без уведомления SCM.
Ответ №1:
Запустите службу, а затем подключите отладчик к запущенному процессу. Поставьте точку останова в serviceCtrlHandler и после WaitForSingleObject(stopEvent, БЕСКОНЕЧНЫЙ) — убедитесь, что, по вашему мнению, должно произойти.
Комментарии:
1. Хорошо. Мне нужно будет установить VS на удаленный компьютер, чтобы получить удаленный отладчик. BBIAW.
2. Проблема заключалась в ошибке с моей стороны. Удаленная отладка устранила эту проблему для меня. Проблема заключалась в том, что когда моя служба завершалась естественным образом, она вызывала serviceCtrlHandler(SERVICE_STOP); который должен быть serviceCtrlHandler(SERVICE_CONTROL_STOP); Это привело к завершению программы без уведомления SCM.
3. @Bluebaron отредактируйте исходный вопрос с решением, чтобы другие могли извлечь выгоду из вашего gaf.