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


Автор: lavan 21.4.2011, 18:44
возник вопрос по созданию служб может кто сможет помочь?.Для создания процесса с одним сервисом,надо иметь 3 
функции:main,servicemain,servicehandle.написал,получаю ошибку:служба запускается как приложение
(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)в мэйн не использовались такие функции как:OpenSCManager,CreateService.
исправил это так:sc create
теперь сервис отображается в окне служб,но после того как я нажимаю старт,сервис вроде как запускается,но ничего не делает
люди не поленитесь,расскажите пошагово как это работает!!!!!
Код

#include<windows.h>
#include<iostream>
#include<fstream>
using namespace std;
static SERVICE_STATUS hs;
static SERVICE_STATUS_HANDLE hstat;
void WINAPI sermain(DWORD argc,LPTSTR argv[]);
void WINAPI serctrlh(DWORD dwcontrol);
LPTSTR sername=_T("MY_TEST");
ofstream out;
int count;
int main() {
SERVICE_TABLE_ENTRY tab[]={{sername,sermain},{NULL,NULL}};
DWORD check;
if(!StartServiceCtrlDispatcher(tab)) {
 check=GetLastError();
 if(check==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
 cout<<"1";
 else if(check==ERROR_INVALID_DATA)
 cout<<"2";
 else if(check==ERROR_SERVICE_ALREADY_RUNNING)
 cout<<"3";
cout<<"\nbug1";
cin.get();
}
return 0;
}
void WINAPI sermain(DWORD argc,LPTSTR argv[]) {
hstat=RegisterServiceCtrlHandler(sername,serctrlh);
if(!hstat) {
out.open("serfile.txt");
if(!out) {
    cout<<"bf1";
    cin.get();
    return;
}
out<<"bug regeterhandle\n";
out.close();
return;
}
hs.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
  hs.dwCurrentState=SERVICE_START_PENDING;
  hs.dwControlsAccepted=SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  hs.dwWin32ExitCode=0;
  hs.dwServiceSpecificExitCode=0;
  hs.dwCheckPoint=0;
  hs.dwWaitHint=5000;
//устанавливаем состояние сервиса
if(!SetServiceStatus(hstat,&hs)) {
out.open("serfile.txt");
if(!out) {
    cout<<"bf2";
    cin.get();
    return;
}
out<<"bug servicestatus 1\n";
out.close();
return;
}
//определяем сервис как работающий
hs.dwCurrentState=SERVICE_RUNNING;
//нет ошибок
hs.dwWin32ExitCode=NO_ERROR;
if(!SetServiceStatus(hstat,&hs)) {
out.open("serfile.txt");
if(!out) {
    cout<<"bug3";
    cin.get();
    return;
}
out<<"bug servicestatus 2\n";
out.close();
return;
}
out.open("serfile.txt");
if(!out) {
    cout<<"bug4";
    cin.get();
    return;
}
out<<"ser is started\n"<<"name is "<<argv[0]<<endl;
//work cicle of service

while(hs.dwCurrentState==SERVICE_RUNNING) {
count++;
Sleep(100);
}

}
void WINAPI serctrlh(DWORD dwcontrol) {


switch(dwcontrol) {
case SERVICE_CONTROL_STOP:
out<<"count="<<count<<endl;
out.close();
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
case SERVICE_CONTROL_SHUTDOWN:
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
}
return;
}


Автор: xvr 22.4.2011, 12:48
Цитата(lavan @  21.4.2011,  18:44 Найти цитируемый пост)
,сервис вроде как запускается,но ничего не делает
люди
Ну так - что просили, то он и делает  smile 

Цитата

Код

while(hs.dwCurrentState==SERVICE_RUNNING) {
count++;
Sleep(100);
}



Цитата(lavan @  21.4.2011,  18:44 Найти цитируемый пост)
люди не поленитесь,расскажите пошагово как это работает!!!!!

В смысле - я тут написал, объясните мне, что именно я написал?  smile 
http://msdn.microsoft.com/en-us/library/ms685967%28v=VS.85%29.aspx

Автор: lavan 22.4.2011, 13:55
весь ваш комент xvr не потеме,прога рабочая,ошибка была в том,что надо было прописывать полный путь к создаваемому лог файлу,и сначало я не понял что через консоль- Службы, при нажатии на старт,автоматически вызываются OpenSCManager(),StartService()
Цитата(xvr @  22.4.2011,  12:48 Найти цитируемый пост)
Ну так - что просили, то он и делает   

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

Автор: xvr 23.4.2011, 07:56
Цитата(lavan @ 22.4.2011,  13:55)
весь ваш комент xvr не потеме,прога рабочая,

Если бы вы внятно сказали, что вы ожидаете от своего сервиса, вам бы ответили. А так - какой вопрос, такой и ответ  smile 
Цитата

вы наверно не стали себя утруждать просмотром кода!потому что код,как минимум должен был создать файл!
Он его создает. В папке windows\system32.  (Или в windows - навскидку не скажу).
Цитата

ошибка была в том,что надо было прописывать полный путь к создаваемому лог файлу,
Т.е. вы считаете, что тут все телепаты и должны были догадаться, что вам лог файл нужен был не в системной папке?  smile 
И код я ваш посмотрел - он ужасен  smile 

Автор: borisbn 23.4.2011, 12:37
Цитата(lavan @  22.4.2011,  13:55 Найти цитируемый пост)
вы наверно не стали себя утруждать просмотром кода!

ВаШкОдНаСтОлЬкОсЛоЖнОчИтАтЬчТоНеТнИкАкОгОжЕлАнИяЭтОдЕлАтЬпОтРуДиТеСьЕгОоТфОрМаТиРоВаТьДлЯнАчАлА

lavan, приятно ?

Автор: lavan 27.4.2011, 18:03
xvr, все ваши комментарии принимаются,не правильная постановка вопроса от непонимания темы!а на счет кода,обычный код для проверки!
borisbn,а как вы видете нормально оформленный код???
попробую задать более четкий вопрос.написал прогу(запускаю кликом по проге)
часть программы:
Код

int main(){
scmanager=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
          if(!scmanager) {
                  return 0;
          }
          if(!GetModuleFileName(NULL,path,256)) {
          return 0;
          }
          if((ser=OpenService(scmanager,MT,SERVICE_ALL_ACCESS))==NULL) {
          service=CreateService(scmanager,MT,sername,NULL,
          SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
          path,NULL,NULL,NULL,NULL,NULL);
          if(!service) {
                  return 0;
          }
          }
          if(ser) {
          StartService(ser,0,0);
          CloseServiceHandle(ser);
          CloseServiceHandle(scmanager);
          }
          else {
          StartService(service,0,0);
          CloseServiceHandle(service);
          CloseServiceHandle(scmanager);
          }
          SERVICE_TABLE_ENTRY tab[]={{MT,servicemain},{NULL,NULL}};
          DWORD check;
if(!StartServiceCtrlDispatcher(tab)) {
                  return 0;
          }
          return 0;
}

выскакивает ошибка:сервис запускается как приложение
но,сервис находится в консоли Службы и через эту консоль его можно запустить.
КАК ИЗБАВИТЬСЯ ОТ ЭТОЙ ОШИБКИ???? 
ели использовать аргументы ком строки то
Код

int main(int argc,char *argv[]) {
if(!strcpm(argv[1],"start")
//вызываем фун которая вызовет OpenSCManager,CreateService,SartService после отработки
....
//попали сюда а здесь сново
StartCtrlDispatchar(...)
//И БУДЕТ ТА ЖА ОШИБКА!если нет,объясните почему?
}

Автор: borisbn 27.4.2011, 18:46
Цитата(lavan @  27.4.2011,  18:03 Найти цитируемый пост)
borisbn,а как вы видете нормально оформленный код???

было
Код

void WINAPI serctrlh(DWORD dwcontrol) {


switch(dwcontrol) {
case SERVICE_CONTROL_STOP:
out<<"count="<<count<<endl;
out.close();
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
case SERVICE_CONTROL_SHUTDOWN:
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
}
return;
}

хотелось бы ( чтоб не разбирать как каракули у врачей smile )
Код

void WINAPI serctrlh(DWORD dwcontrol) {
    switch(dwcontrol) {
        case SERVICE_CONTROL_STOP:
            out << "count=" << count << endl;
            out.close();
            hs.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(hstat,&hs);
        break;
        case SERVICE_CONTROL_SHUTDOWN:
            hs.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(hstat,&hs);
        break;
    }
    return;
}

Автор: xvr 27.4.2011, 19:52
Цитата(lavan @  27.4.2011,  18:03 Найти цитируемый пост)
КАК ИЗБАВИТЬСЯ ОТ ЭТОЙ ОШИБКИ????

Никак. Сервис (именно как сервис) может быть запущен только системой, и только при таком запуске функция StartServiceCtrlDispatcher будет работать.
Собственно в сервисах есть 2 совершенно независимых части - регистрация и управление сервисом (это OpenSCManager и все, что от него растет). И сам сервис - это StartServiceCtrlDispatcher  и все что от него растет.
Управление - это обычное приложение, оно даже не обязано содержаться в том же exe, что и сам сервис (StartServiceCtrlDispatcher). 
Собственно 'консоли Службы' этим интерфейсом и пользуется

Сам сервис же запускается (по команде из 1й части) специальным системным процессом (servises.exe)

Собственно, когда вы вызываете StartService из своей программы (той, что два в одном  smile ), то сервис мэнеджер (servises.exe) запускает 2й экземпляр вашей программы, который и становится сервисом, а 1й экземпляр (тот, что вызывал StartService) завершается

Автор: ASMatic 29.4.2011, 03:05
не особо там вычитывая но понимая траблу с сервисаме)
Код

#define SERVICE_NAME        L"TestService"
#define DEFAULT_HINT_TIME   3000

SERVICE_STATUS          SvcStatus;
SERVICE_STATUS_HANDLE   hSvcStatus;
HANDLE                  hMainSvcThread;

INT
main(
    VOID
    )
{
    SERVICE_TABLE_ENTRY     SvcEntries[2] = { 0 };

    SvcEntries[0].lpServiceName = SERVICE_NAME;
    SvcEntries[0].lpServiceProc = ServiceMain;

    if (!StartServiceCtrlDispatcher( SvcEntries )) {
        return SVC_ERROR;
    }

    return NO_ERROR;
}

VOID
WINAPI
ServiceMain(
    IN      DWORD   dwArgc,
    IN      LPTSTR  *lpszArgv
    )
{
    hSvcStatus = RegisterServiceCtrlHandlerEx( NULL,
                                               (LPHANDLER_FUNCTION_EX)SvcHandlerEx,
                                               NULL );
    if (hSvcStatus == NULL)
        return;

    //
    //Fill service status struct
    //
    SvcStatus.dwCheckPoint = 0;
    SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SESSIONCHANGE;
    SvcStatus.dwServiceSpecificExitCode = 0;
    SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    SvcStatus.dwWaitHint = DEFAULT_HINT_TIME;
    SvcStatus.dwWin32ExitCode = NO_ERROR;

    ReportSvcStatus( SERVICE_START_PENDING );

    ServiceInit();
}

VOID
ReportSvcStatus(
    IN      DWORD   CurrentState
    )
{
    ReportSvcStatusEx( CurrentState,
                       NO_ERROR,
                       DEFAULT_HINT_TIME );
}

VOID
ReportSvcStatusEx(
    IN      DWORD   CurrentState,
    IN      DWORD   Win32ExitCode,
    IN      DWORD   WaitHint
    )
{
    static DWORD    CheckPoint = 1;

    SvcStatus.dwCurrentState = CurrentState;
    SvcStatus.dwWin32ExitCode = Win32ExitCode;
    SvcStatus.dwWaitHint = WaitHint;

    /*
    //if don`t use CheckPoints this bite of code can be deleted
    if ( (CurrentState == SERVICE_RUNNING) || (CurrentState == SERVICE_STOPPED) )
        SvcStatus.dwCheckPoint = 0;
    else
        SvcStatus.dwCheckPoint = CheckPoint++;
    */

    //Report SCM
    SetServiceStatus( hSvcStatus,
                      &SvcStatus );
}

VOID
WINAPI
SvcHandlerEx(
    IN      DWORD   Control,
    IN      DWORD   EventType,
    IN      LPVOID  EventData,
    IN      LPVOID  Context
    )
{
    DWORD   State;

    switch (Control) {

        case SERVICE_CONTROL_STOP:
            ReportSvcStatus( SERVICE_STOPPED );
            return;

        default:
            State = SERVICE_RUNNING;
    }

    ReportSvcStatus( State );
}

VOID
ServiceInit(
    VOID
    )
{
    DWORD   result;

    result = SafeCreateThread( &hMainSvcThread,
                               MainSvcThread,
                               NULL );
    if (result != NO_ERROR) {
        StopService( NULL,
                     0 );
    }

    SvcStatus.dwWaitHint = 0;
    SvcStatus.dwCheckPoint = 0;
    ReportSvcStatus( SERVICE_RUNNING );
}

VOID
StopService(
    IN      PWCHAR  Event,
    IN      DWORD   ErrorCode
    )
{
    ReportSvcStatus( SERVICE_STOP );
    ExitProcess( ErrorCode );
}

DWORD
WINAPI
MainSvcThread(
    IN      PVOID   Parameter
    )
{
    return NO_ERROR;
}


РАБОЧИЙ СЕРВИС! - инсталь и юзай.)
*есессно код для тестов.

Автор: lavan 1.5.2011, 19:35
Всем спасибо за помощь,вроде разобрался!

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