Текущий архив: 2006.09.03;
Скачать: CL | DM;
Вниз
Проблемы с сервисом Найти похожие ветки
← →
ПЛОВ © (2006-08-07 16:13) [0]Написал болванку сервиса с использованием предоставленных мне примеров и информации из MSDN. Вроде все правильно. Сервис устанавливаеться и удаляеться без проблем. Но упорно не желает запускаться. StartServiceCtrlDispatcherA выдает ошибку. Подозреваю что для "минимального сервсиса" чего-то не хватает но не могу понять чего...
const PCHAR ServName = "test";
const PCHAR ServDispName = "test";
CHAR szPath[MAX_PATH];
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS srvStat;
SERVICE_STATUS_HANDLE srvStatHandle;
//-----------------------------------------------------
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
...
SERVICE_TABLE_ENTRYA DispatchTable[] =
{
{ServName, (LPSERVICE_MAIN_FUNCTIONA)ServiceProcA},
{NULL, NULL}
};
//запуск
if (!StartServiceCtrlDispatcherA(DispatchTable)) // тут ошибка
WriteError("StartServiceCtrlDispatcherA failed", GetLastError()); // - возвращает 1063
return 0;
}
остальное имеет такой вид (практически полностью взято из MSDN)
// Stub initialization function.
DWORD ServiceInitializationA(DWORD argc, PCHAR * argv, DWORD * specificError)
{
argv;
argc;
specificError;
return(0);
}
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
// Do whatever it takes to pause here.
srvStat.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
// Do whatever it takes to continue here.
srvStat.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here.
srvStat.dwWin32ExitCode = 0;
srvStat.dwCurrentState = SERVICE_STOPPED;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
if (!SetServiceStatus(srvStatHandle, &srvStat))
{
status = GetLastError();
WriteError("SetServiceStatus failed", status);
}
WriteLog("Leaving Service");
return;
case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;
default:
WriteError("Unrecognized opcode", Opcode);
}
// Send current status.
if (!SetServiceStatus (srvStatHandle, &srvStat))
{
status = GetLastError();
WriteError("SetServiceStatus failed", status);
}
return;
}
//---------------------------------------------------------------------------------------
void WINAPI ServiceProcA(DWORD argc, LPSTR * argv)
{
DWORD status;
DWORD specificError;
srvStat.dwServiceType = SERVICE_WIN32;
srvStat.dwCurrentState = SERVICE_START_PENDING;
srvStat.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
srvStat.dwWin32ExitCode = 0;
srvStat.dwServiceSpecificExitCode = 0;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
srvStatHandle = RegisterServiceCtrlHandlerA(ServName, ServiceCtrlHandler);
if (srvStatHandle == (SERVICE_STATUS_HANDLE)0)
{
WriteError("RegisterServiceCtrlHandlerA failed", GetLastError());
return;
}
status = ServiceInitializationA(argc, argv, &specificError);
// Handle error condition
if (status != NO_ERROR)
{
srvStat.dwCurrentState = SERVICE_STOPPED;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
srvStat.dwWin32ExitCode = status;
srvStat.dwServiceSpecificExitCode = specificError;
SetServiceStatus(srvStatHandle, &srvStat);
return;
}
// Initialization complete - report running status.
srvStat.dwCurrentState = SERVICE_RUNNING;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
if (!SetServiceStatus(srvStatHandle, &srvStat))
{
status = GetLastError();
WriteError("SetServiceStatus failed", status);
}
// This is where the service does its work.
WriteLog("!типа сработало!");
return;
}
← →
isasa © (2006-08-07 16:32) [1]А если вот так, как в примерах? :)
SERVICE_TABLE_ENTRY dispTable[] = {
{ (LPTSTR)ServName, ServiceProcA},
{ NULL, NULL}
};
if (!StartServiceCtrlDispatcher((LPSERVICE_TABLE_ENTRY)&dispTable[0]))
...
Кроме этого, фигня какая то.
const PCHAR ServName = "test";
const PCHAR ServDispName = "test";
Надо бы так. С юникодом(жирным).
const TCHAR ServName = _T("test");
const TCHAR ServDispName = _T("test");
← →
isasa © (2006-08-07 16:35) [2]Да и еще, "главная" - желательно простое консольное приложение
неint APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
аint _tmain(int argc, _TCHAR* argv[])
← →
ПЛОВ © (2006-08-07 16:38) [3]Не может же быть ошибочной вся функция StartServiceCtrlDispatcherA? Я уже все остальное написал именно под А, так сказать, переписать конечно можно, но и это должно работать :(
← →
ПЛОВ © (2006-08-07 16:42) [4]Неужели сервис может работать только с юникодом и только в консольном приложении?
← →
isasa © (2006-08-07 16:46) [5]А при чем здесь А, W ...
ServiceProcA, ServiceCtrlHandler - это просто твои имена твоих точек входа, называй как хочешь. Имя сервиса в юникоде.
Хотя здесь неправилино заполнена dispTable.
← →
ПЛОВ © (2006-08-07 16:54) [6]
> Хотя здесь неправилино заполнена dispTable.
Неправильно в плане НЕиспользования юникода? Но ведь есть же SERVICE_TABLE_ENTRYA, StartServiceCtrlDispatcherA значит эти функции должны работать с Анси-строками...
← →
isasa © (2006-08-07 17:02) [7]Меня глежет смутные сомнения, как запускаем то?
← →
ПЛОВ © (2006-08-07 17:14) [8]
> Меня глежет смутные сомнения, как запускаем то?
Через панель управления стандартно.
Только что переустановил сервис и он стал запускаться (мистика :) ) Но как бы формально, потому что эта строка не выполняеться:// This is where the service does its work.
WriteLog("!типа сработало!");
Хотя возможно и не должна...
← →
ПЛОВ © (2006-08-07 17:27) [9]И еще такой вопрос, как я понимаю, события, указанные в ServiceCtrlHandler вроде SERVICE_CONTROL_PAUSE вызываються тогда, когда с севисом производиться указанное действие, правильно? Я добавил туда запись всех этих действий в лог-файл. Ничего не пишеться.
← →
isasa © (2006-08-07 17:29) [10]Ну, слава Богу. Для приличия можно добавить уведомление о завершении ...
// This is where the service does its work.
WriteLog("!типа сработало!");
//
srvStat.dwCurrentState = SERVICE_STOPPED;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
srvStat.dwWin32ExitCode = status;
srvStat.dwServiceSpecificExitCode = specificError;
SetServiceStatus(srvStatHandle, &srvStat);
← →
isasa © (2006-08-07 17:37) [11]ПЛОВ © (07.08.06 17:27) [9]
Куда, туда? :)
SERVICE_CONTROL_PAUSE и иже, это только уведемления о том, что надо тормозить. Тормозить должен сам(руками или чем придется). Посмотри примеры на основе потока. Очень удобно. Тормозишь и посылаешь уведомление....
case SERVICE_CONTROL_PAUSE:
srvStat.dwCurrentState = SERVICE_PAUSED;
SuspendThread(mhThread);
...
case SERVICE_CONTROL_CONTINUE:
srvStat.dwCurrentState = SERVICE_RUNNING;
ResumeThread(mhThread);
...
if (!SetServiceStatus (srvStatHandle, &srvStat)) ...
← →
ПЛОВ © (2006-08-07 17:37) [12]
> Ну, слава Богу. Для приличия можно добавить уведомление
> о завершении ...
Добавил... Вроде код работает, сервис запускаеться и сразу-же выдаеться сообщение о его остановке (оно?), но лог не ведеться!
← →
Ketmar © (2006-08-07 17:48) [13]оффтоп.
> [11] isasa © (07.08.06 17:37)
> Тормозить должен сам(руками или чем придется).
долго плакал. tnx. %-)
← →
isasa © (2006-08-07 17:48) [14]Естественно не выдаст, если ты иеешь ввиду "Leaving Service", т.к. оно стоит после уведомления о завершении. А ты переставо до...
case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here.
srvStat.dwWin32ExitCode = 0;
srvStat.dwCurrentState = SERVICE_STOPPED;
srvStat.dwCheckPoint = 0;
srvStat.dwWaitHint = 0;
if (!SetServiceStatus(srvStatHandle, &srvStat))
{
status = GetLastError();
WriteError("SetServiceStatus failed", status);
}
WriteLog("Leaving Service"); //<----
← →
isasa © (2006-08-07 17:50) [15]Ketmar © (07.08.06 17:48) [13]
Хотел написать тем, что было в инструкции по пользованию шведской бензопилой, но постеснялся ...
← →
ПЛОВ © (2006-08-07 17:52) [16]Да, я поставил сразу после каждого
case SERVICE_CONTROL_что-то
WriteLog
Не пишеться. Вот порыскал и нашел описание своей ошибки:
FAILED_SERVICE_CONTROLLER
Процесс службы не может установить связь с контроллером службы
← →
isasa © (2006-08-07 18:00) [17]Добавь фрагмент
if (error) {
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL );
wprintf(L"Error message. (0x%08X)%s\n", dw, lpMsgBuf);
LocalFree(lpMsgBuf);
return ...
}
и не будешь рыскать в поисках текта сообщения о ошибке.
Фрагмент для юникода.
Преобразования вывода на консоль CharToOem.
← →
ПЛОВ © (2006-08-07 18:03) [18]
> и не будешь рыскать в поисках текта сообщения о ошибке
Главное ее найти и уничтожить :)
← →
ПЛОВ © (2006-08-07 18:12) [19]Объясните хоть что она означает? Чтобы знать куда копать...
← →
isasa © (2006-08-07 18:18) [20]ПЛОВ © (07.08.06 18:12) [19]
Это ты про
isasa © (07.08.06 18:00) [17]
← →
ПЛОВ © (2006-08-07 18:20) [21]
> isasa © (07.08.06 18:18) [20]
Я про саму ошибку FAILED_SERVICE_CONTROLLER. Что она означает? Из описания мало что понятно...
Страницы: 1 вся ветка
Текущий архив: 2006.09.03;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.031 c