Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Windows Service не стартует


Автор: freezeman 26.2.2012, 13:35
Всем привет!

Подскажите, пожалуйста, почему служба не запускается? Код проходит без ошибок, но проверяю диспетчер служб и не нахожу созданную службу...

Код:
Код

#include "stdafx.h"
#include <windows.h>
#include <winsvc.h>

void ServiceMain(DWORD argc, LPTSTR *argv); 
void ServiceCtrlHandler(DWORD nControlCode);
BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
                     DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
                     DWORD dwWaitHint);
BOOL StartServiceThread();
DWORD ServiceExecutionThread(LPDWORD param);
HANDLE hServiceThread;
void KillService();

char *strServiceName = "NishFirstService";
SERVICE_STATUS_HANDLE nServiceStatusHandle; 
HANDLE killServiceEvent;
BOOL nServiceRunning;
DWORD nServiceCurrentStatus;

void main(int argc, char* argv[])
{
    SERVICE_TABLE_ENTRY servicetable[]=
    {
        {(LPWSTR)strServiceName,
        (LPSERVICE_MAIN_FUNCTION)ServiceMain},
        {NULL,NULL}
    };
    BOOL success;
    success=StartServiceCtrlDispatcher(servicetable);
    if(!success)
    {
        //error occured
    }
}

void ServiceMain(DWORD argc, LPTSTR *argv)
{
    BOOL success;
    nServiceStatusHandle=RegisterServiceCtrlHandler(
        (LPWSTR)strServiceName,
        (LPHANDLER_FUNCTION)ServiceCtrlHandler);
    if(!nServiceStatusHandle)
    {
        return;
    }
    success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,1,3000);
    if(!success)
    {
        return;
    }
    killServiceEvent=CreateEvent(0,TRUE,FALSE,0);
    if(killServiceEvent==NULL)
    {
        return;
    }
    success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,2,1000);
    if(!success)
    {
        return;
    }
    success=StartServiceThread();
    if(!success)
    {
        return;
    }
    nServiceCurrentStatus=SERVICE_RUNNING;
    success=UpdateServiceStatus(SERVICE_RUNNING,NO_ERROR,0,0,0);
    if(!success)
    {
        return;
    }
    WaitForSingleObject(killServiceEvent,INFINITE);
    CloseHandle(killServiceEvent);
}



BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
                     DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
                     DWORD dwWaitHint)
{
    BOOL success;
    SERVICE_STATUS nServiceStatus;
    nServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
    nServiceStatus.dwCurrentState=dwCurrentState;
    if(dwCurrentState==SERVICE_START_PENDING)
    {
        nServiceStatus.dwControlsAccepted=0;
    }
    else
    {
        nServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP            
            |SERVICE_ACCEPT_SHUTDOWN;
    }
    if(dwServiceSpecificExitCode==0)
    {
        nServiceStatus.dwWin32ExitCode=dwWin32ExitCode;
    }
    else
    {
        nServiceStatus.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
    }
    nServiceStatus.dwServiceSpecificExitCode=dwServiceSpecificExitCode;
    nServiceStatus.dwCheckPoint=dwCheckPoint;
    nServiceStatus.dwWaitHint=dwWaitHint;

    success=SetServiceStatus(nServiceStatusHandle,&nServiceStatus);

    if(!success)
    {
        KillService();
        return success;
    }
    else
        return success;
}

BOOL StartServiceThread()
{    
    DWORD id;
    hServiceThread=CreateThread(0,0,
        (LPTHREAD_START_ROUTINE)ServiceExecutionThread,
        0,0,&id);
    if(hServiceThread==0)
    {
        return false;
    }
    else
    {
        nServiceRunning=true;
        return true;
    }
}

DWORD ServiceExecutionThread(LPDWORD param)
{
    while(nServiceRunning)
    {        
        Beep(450,150);
        Sleep(4000);
    }
    return 0;
}

void KillService()
{
    nServiceRunning=false;
    SetEvent(killServiceEvent);
    UpdateServiceStatus(SERVICE_STOPPED,NO_ERROR,0,0,0);
}

void ServiceCtrlHandler(DWORD nControlCode)
{
    BOOL success;
    switch(nControlCode)
    {    
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
        nServiceCurrentStatus=SERVICE_STOP_PENDING;
        success=UpdateServiceStatus(SERVICE_STOP_PENDING,NO_ERROR,0,1,3000);
        KillService();        
        return;
    default:
        break;
    }
    UpdateServiceStatus(nServiceCurrentStatus,NO_ERROR,0,0,0);
}



При StartServiceCtrlDispatcher выдает ошибку 1063!!!

Автор: freezeman 26.2.2012, 15:38
Подскажите, в чем может быть проблема? Именно при запуске (StartServiceCtrlDispatcher) выдает ошибку. Пробовал как на XP x86, так и на Win 7 x86.
Error 1063

Автор: feodorv 26.2.2012, 16:30
Цитата(freezeman @  26.2.2012,  13:35 Найти цитируемый пост)
void ServiceMain(DWORD argc, LPTSTR *argv)

Может, 
Цитата

VOID WINAPI ServiceMain(...)

Хотя 
Цитата(freezeman @  26.2.2012,  15:38 Найти цитируемый пост)
Error 1063 
 не об этом.

Ну и
Цитата(freezeman @  26.2.2012,  13:35 Найти цитируемый пост)
        {(LPWSTR)strServiceName,

Может, (LPТSTR)...?

Автор: freezeman 26.2.2012, 18:21
Цитата(feodorv @ 26.2.2012,  16:30)
Цитата(freezeman @  26.2.2012,  13:35 Найти цитируемый пост)
void ServiceMain(DWORD argc, LPTSTR *argv)

Может, 
Цитата

VOID WINAPI ServiceMain(...)

Хотя 
Цитата(freezeman @  26.2.2012,  15:38 Найти цитируемый пост)
Error 1063 
 не об этом.

Ну и
Цитата(freezeman @  26.2.2012,  13:35 Найти цитируемый пост)
        {(LPWSTR)strServiceName,

Может, (LPТSTR)...?

Спасибо за ответ! Я решил взять пример http://www.rsdn.ru/article/files/Classes/svcclass.xml, все прекрасно описывается.

Но не могу теперь найти место, где выполнять мой код!! Может звучит глупо, но, как я понимаю, он должен располагаться в ServiceMain, пытаюсь вывести что-нибудь в файл, но ничего происходит... 

Прикрепил проект!

Для запуска необходимо в командной строке указать ключ -install и запустить службу.

Добавлено через 5 минут и 13 секунд
Небольшая поправка, мой код выполняется в ServiceMain только после перезапуска или остановки службы (т.е. когда я запустил службу ничего не произошло, но после её остановки или перезапуска код начинает выполняться и пишет в файл)

Каким это образом может происходить???

Автор: feodorv 26.2.2012, 18:46
Цитата(freezeman @  26.2.2012,  18:21 Найти цитируемый пост)
т.е. когда я запустил службу 

А каки образом это происходит?

Автор: freezeman 26.2.2012, 21:03
Цитата(feodorv @ 26.2.2012,  18:46)
Цитата(freezeman @  26.2.2012,  18:21 Найти цитируемый пост)
т.е. когда я запустил службу 

А каки образом это происходит?

Скомпилировав exe, через командную строку передаю ключ -install

Автор: feodorv 26.2.2012, 22:14
Цитата(freezeman @  26.2.2012,  21:03 Найти цитируемый пост)
Скомпилировав exe, через командную строку передаю ключ -install 

Как я понимаю, этим сервис лишь прописывается в системе как сервис, но никак не запускается. А сам сервис стартует запуском экзешника без указания опций запуска:
Код

    if (nArgc < 2){
        CServiceHelper serv;            //Создаем объект-помошник для запуска и управления службами
        serv.AddService(L"SServ1",ServiceMain1);//Добавление службы с указанием ее имени
        serv.AddService(L"SServ2",ServiceMain2);//и процедуры ServiceMain
        serv.Start();                    //Вызов StartServiceCtrlDispatcher()
        return 0;                    //Все службы остановлены, выход их программы
    }


То есть:
  • xxx.exe -install   - прописывается в ОС
  • xxx.exe              - стартуем сервис и дожидаемся его завершения
  • xxx.exe -remove - удаляем сервис из системы

Не хватает
  • xxx.exe -stop     - останов сервиса (без удаления)
 smile 

Автор: xvr 27.2.2012, 12:46
Цитата(feodorv @  26.2.2012,  22:14 Найти цитируемый пост)
Как я понимаю, этим сервис лишь прописывается в системе как сервис, но никак не запускается.

Да

Цитата(feodorv @  26.2.2012,  22:14 Найти цитируемый пост)
А сам сервис стартует запуском экзешника без указания опций запуска:

Нет. 'Просто запускать' его должен Service Manager, а не пользователь. Можно из панели управления, либо с коммандной строки через net start SServ1

Автор: freezeman 27.2.2012, 12:53
Цитата(xvr @ 27.2.2012,  12:46)
Цитата(feodorv @  26.2.2012,  22:14 Найти цитируемый пост)
Как я понимаю, этим сервис лишь прописывается в системе как сервис, но никак не запускается.

Да

Цитата(feodorv @  26.2.2012,  22:14 Найти цитируемый пост)
А сам сервис стартует запуском экзешника без указания опций запуска:

Нет. 'Просто запускать' его должен Service Manager, а не пользователь. Можно из панели управления, либо с коммандной строки через net start SServ1

Мне нужно создать в службе 3 потока, где их запускать в ServiceMain?

Автор: feodorv 27.2.2012, 13:11
Цитата(xvr @  27.2.2012,  12:46 Найти цитируемый пост)
Нет. 'Просто запускать' его должен Service Manager, а не пользователь.

Мда, точно, в функциональность этого экзешника не входит старт/стоп сервиса...

Цитата(freezeman @  27.2.2012,  12:53 Найти цитируемый пост)
Мне нужно создать в службе 3 потока, где их запускать в ServiceMain? 

Зависит от задачи. Если это три сервиса, то на каждый нужен свой ServiceMain:
Цитата(feodorv @  26.2.2012,  22:14 Найти цитируемый пост)
       serv.AddService(L"SServ1",ServiceMain1);//Добавление службы с указанием ее имени
        serv.AddService(L"SServ2",ServiceMain2);//и процедуры ServiceMain

Если это один сервис, но с тремя потоками, тогда одна процедура ServiceMain и запуск потоков из ServiceMain после RegisterServiceCtrlHandlerEx.

Добавлено через 11 минут и 54 секунды
Только надо учесть, что один поток у Вас уже есть)))

Автор: xvr 27.2.2012, 13:42
Цитата(freezeman @  26.2.2012,  18:21 Найти цитируемый пост)
Я решил взять пример здесь, все прекрасно описывается.

Угу, вот только 'минимальным' я бы его не назвал  smile 

Цитата(freezeman @  27.2.2012,  12:53 Найти цитируемый пост)
Мне нужно создать в службе 3 потока, где их запускать

В вашей библиотеке - в наследнике CServiceContext в методе OnServiceStart() (и не забыть их завершить в методе OnServiceStop() )

Автор: freezeman 27.2.2012, 14:52
Цитата(xvr @ 27.2.2012,  13:42)
Цитата(freezeman @  26.2.2012,  18:21 Найти цитируемый пост)
Я решил взять пример здесь, все прекрасно описывается.

Угу, вот только 'минимальным' я бы его не назвал  smile 

Цитата(freezeman @  27.2.2012,  12:53 Найти цитируемый пост)
Мне нужно создать в службе 3 потока, где их запускать

В вашей библиотеке - в наследнике CServiceContext в методе OnServiceStart() (и не забыть их завершить в методе OnServiceStop() )

Да, минимальными их назвать трудно))

Я вписывал туда код записи в файл для проверки, но ничего не происходит...Может из-за того, что я сервис стартовал из Диспетчера служб Windows... 
Я ещё подумал, может сделать службу на C# и из нее запускать exe, где запускаются все 3 потока???

Автор: xvr 27.2.2012, 18:54
Цитата(freezeman @  27.2.2012,  14:52 Найти цитируемый пост)
Я вписывал туда код записи в файл для проверки, но ничего не происходит...

Вставьте запуск нитей непосредственно в ServiceMain перед последним вызовом.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)