ginglese
15-04-2005 07:24:50
bonjour,
auriez vous des exemples de codes c++ pour créer un service windows.
j'en ei créer un mais je dois passer par une ligne de commande dans mon programme pour l'ajouter, le supprimer, le démarrer et l'arrêter.
est il possible de faire tous cela dans des fonctions c++ et pas par un appel system ?
merci.
fabrice.roge
15-04-2005 12:48:05
Tiens une petite classe de mon cru mon faire ce que tu veux assez simplement avec un service win32.
Win32ServiceInterface.h
**********************
#ifndef __WS32SA_
#define __WS32SA_
#include "stdafx.h"
#define SW32SA_STATE_STOP 0
#define SW32SA_STATE_RUN 1
#define SW32SA_STATE_PAUSE 2
typedef short SW32SA_STATE ;
class SimpleWin32ServiceAdapter
{
private:
LPSTR _lsz_name, _lsz_path;
LPSERVICE_MAIN_FUNCTION _ServiceMain;
LPHANDLER_FUNCTION _ServiceCtrlHandler;
SW32SA_STATE state;
SERVICE_STATUS_HANDLE hStatus;
SERVICE_STATUS status;
public:
SimpleWin32ServiceAdapter(LPCTSTR csz_name, LPCTSTR cs_binary_path,
LPSERVICE_MAIN_FUNCTION ServiceMain,LPHANDLER_FUNCTION ServiceCtrlHandler);
SimpleWin32ServiceAdapter(LPCTSTR csz_name, LPCTSTR cs_binary_path);
~SimpleWin32ServiceAdapter();
//predefined service control facilities
bool setState(SW32SA_STATE state);
SW32SA_STATE getState();
bool bootSvc();
bool registerCtrler();
//registration functions
bool registerService();
bool unregisterService();
};
typedef SimpleWin32ServiceAdapter * LPSW32SA, SW32SA ;
#endif
************************
Win32ServiceInterface.cpp
******************************************
#include "stdafx.h"
#include "Win32ServiceInterface.h"
SimpleWin32ServiceAdapter::SimpleWin32ServiceAdapter(LPCTSTR csz_name,LPCTSTR csz_path,
LPSERVICE_MAIN_FUNCTION pServiceMain,LPHANDLER_FUNCTION pServiceCtrlHandler)
{
if (csz_name)
this->_lsz_name = strdup(csz_name);
if (csz_path)
this->_lsz_path = strdup( csz_path);
if (pServiceMain)
this->_ServiceMain = pServiceMain;
if (pServiceCtrlHandler)
this->_ServiceCtrlHandler = pServiceCtrlHandler;
this->state=SW32SA_STATE_STOP;
}
SimpleWin32ServiceAdapter::SimpleWin32ServiceAdapter(LPCTSTR csz_name,LPCTSTR csz_path)
{
if (csz_name)
this->_lsz_name = strdup(csz_name);
if (csz_path)
this->_lsz_path = strdup( csz_path);
this->_ServiceCtrlHandler=NULL;
this->_ServiceMain=NULL;
this->state=SW32SA_STATE_STOP;
}
SimpleWin32ServiceAdapter::~SimpleWin32ServiceAdapter()
{
if (_lsz_name)
{
delete _lsz_name;_lsz_name = NULL;
}
if (_lsz_path)
{
delete _lsz_path;_lsz_path = NULL;
}
this->_ServiceCtrlHandler=NULL;
this->_ServiceMain=NULL;
}
bool SimpleWin32ServiceAdapter::setState(SW32SA_STATE state)
{
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
status.dwControlsAccepted= SERVICE_ACCEPT_STOP;
status.dwWin32ExitCode=NO_ERROR ;
status.dwCheckPoint=0;
status.dwWaitHint=1000;
switch(state)
{
case (SW32SA_STATE_STOP):
status.dwCurrentState = SERVICE_STOPPED;
this->state = state;
break;
case (SW32SA_STATE_RUN):
status.dwCurrentState = SERVICE_RUNNING;
this->state = state;
break;
case (SW32SA_STATE_PAUSE):
status.dwCurrentState = SERVICE_PAUSED;
this->state = state;
break;
default:
return false;
break;
}
if (!SetServiceStatus(hStatus,&status))
return false;
return true;
}
SW32SA_STATE SimpleWin32ServiceAdapter::getState()
{
return this->state;
}
bool SimpleWin32ServiceAdapter::bootSvc( )
{
if ( !this->_ServiceMain)
return false;
SERVICE_TABLE_ENTRY ste_service ;
ste_service.lpServiceName = this->_lsz_name;
ste_service.lpServiceProc = this->_ServiceMain;
SERVICE_TABLE_ENTRY null_terminator = {NULL,NULL};
LPSERVICE_TABLE_ENTRY svc_table = new SERVICE_TABLE_ENTRY[2];
svc_table[0] = ste_service;
svc_table[1] = null_terminator;
if (! ( StartServiceCtrlDispatcher(svc_table) ) )
{
delete svc_table;svc_table = NULL;
return false;
}
delete svc_table;svc_table=NULL;
return true;
}
bool SimpleWin32ServiceAdapter::registerCtrler()
{
if (!this->_lsz_name || !this->_ServiceCtrlHandler )
return false;
if (
!(hStatus = RegisterServiceCtrlHandler(this->_lsz_name,this->_ServiceCtrlHandler))
)
{
hStatus=NULL;
return false;
}
return true;
}
bool SimpleWin32ServiceAdapter::registerService()
{
SC_HANDLE hSCManager, hSCService;
if ( ! (hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE)) )
return false;
if ( !_lsz_name || !_lsz_path || ! (hSCService = CreateService(hSCManager,this->_lsz_name,this->_lsz_name, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DISABLED, // start type
SERVICE_ERROR_NORMAL, // error control type
this->_lsz_path, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL)
))// no password
return false;
CloseServiceHandle(hSCService);
hSCManager = NULL;
hSCService = NULL;
return true;
}
bool SimpleWin32ServiceAdapter::unregisterService()
{
SC_HANDLE hSCService, hSCManager ;
if (! ( hSCManager=OpenSCManager(NULL,NULL,STANDARD_RIGHTS_REQUIRED) ) )
return false;
if ( !_lsz_name || ! ( hSCService = OpenService ( hSCManager, this->_lsz_name, STANDARD_RIGHTS_REQUIRED) ) )
return false;
if ( ! ( DeleteService ( hSCService ) ) )
return false;
CloseServiceHandle(hSCService);
hSCManager = NULL;
hSCService = NULL;
return true;
}
******************************************
example d'utilisation dans ton main:
SW32SA w32_svc = SW32SA("my_service","C:\\projets\\versioning\\mon_service.exe 2");
l'ajouter:
w32_svc.registerService();
le supprimer :
w32_svc.unregisterService();
le démarrer:
w32_service = new SW32SA("my_service",
"C:\\projets\\versioning\\mon_service.exe 2",
&serviceMain,
&serviceCtrlHandler
);
if (!w32_service->bootSvc())
exit(1);
Tu dois déclarer pour celà serviceMain et serviceCtrlHandlr, examples:
void WINAPI serviceCtrlHandler(DWORD Opcode)
{
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
w32_service->setState(SW32SA_STATE_STOP);
break;
case SERVICE_CONTROL_CONTINUE:
w32_service->setState(SW32SA_STATE_STOP);
break;
case SERVICE_CONTROL_STOP:
w32_service->setState(SW32SA_STATE_STOP);
break;
case SERVICE_CONTROL_INTERROGATE:
w32_service->setState(SW32SA_STATE_STOP);
break;
}
return;
}
void WINAPI serviceMain(DWORD argc,LPTSTR * argv)
{
//register the controller, must be done here : mandatory
if (!w32_service->registerCtrler())
{
LogFailure(MSG_START_FAILED);
exit(1);
}
w32_service->setState(SW32SA_STATE_RUN);
LogSuccess(MSG_START_SUCCESS );
while (w32_service->getState()==SW32SA_STATE_RUN)
{
//do some stuff here
// TODO: code your application's behavior here.
// ....
{
delete w32_service;w32_service = NULL;
exit(0);
}
Sinon je ne sais pas bien par quelle commande shell tu passes pour creér ou supprimer ton service, mais il est clair que ton programme doit analyser les paramètres qui lui sont passés par la ligne de commande pour savoir quoi faire (ici 2 indique que le service doit s'exécuter, et 1 ainsi que 0 pour respectivement le register et le unregister).
C'est un example comme un autre, mais si j'ai fait cette classe c'est pour avoir tous les appels système dans une seule classe plutot que de devoir tout recoder à chaque fois que je crée des services. C'est une sorte de wrapper en somme.
Juste une chose ça a été codé à l'arrache donc il peut y avoir des erreurs dedans même si c'est censer fonctionner correctement autant que je sache.
Bon courage.
ginglese
15-04-2005 13:41:25
merci je vais voir cela de plus prêt.
ginglese
15-04-2005 17:41:51
ok.
j'avais pas fait attention que l'on pouvait créer le service en appelant la methode create Service en dehors de l'exe du service lui-même .
du coup je peux faire mes appels d'ajout/suppresion et démmarage/ arrêt depuis mon programme sans passer par les commandes shells.
merci !
fabrice.roge
15-04-2005 20:07:06
Ben de rien si je peux rendre service
ginglese
16-04-2005 10:24:09
au fait comment fait on pour marquer le sujet en [Résolu] ?
theocrite
16-04-2005 14:09:51
Tu édites ton premier post