PDA

Visualizza la versione completa : [c++]classe servizio nt non funzionante


whitedemon
03-12-2011, 12:06
ragazzi sono nuovo del forum e colgo l'occasione per salutare tutti(specialmente quelli che mi saranno d'aiuto:P)... sto provando a creare una classe in c++ che crei/installi e gestica un servizio di windows... il codice che sto per linkarvi viene correttamente compilato dal compilatore, installa il servizio su windows senza nessun problema, ma quando provo a lanciarlo mi da errore 1067 -.-'. PLEASE HELP ME!!!!

<servizio.h>

#include <process.h>
#include <iostream>
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include <winsvc.h>

#ifndef SERVIZIO_H
#define SERVIZIO_H

const int nBufferSize = 500;

class servizio
{
public:
servizio();
void ServiceMainProc();
void set_cmd(char*);
char *get_cmd();
char *get_pExeFile();
void set_pServiceName(char*);
char *get_pServiceName();
void set_pLogFile(char*);
char *get_pLogFile();
virtual ~servizio();
protected:
virtual void ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
virtual void ServiceHandler(DWORD fdwControl);
private:
void Install();
void UnInstall();
void WriteLog(char* pMsg);
bool KillService();
bool RunService();
void ExecuteSubProcess();
friend void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
friend void WINAPI ServiceHandler(DWORD fdwControl);
bool ProcessStarted;
SERVICE_STATUS_HANDLE hServiceStatusHandle;
SERVICE_STATUS ServiceStatus;
CRITICAL_SECTION myCS;
SERVICE_TABLE_ENTRY lpServiceStartTable[2];
char pServiceName[nBufferSize+1];
char pExeFile[nBufferSize+1];
char lpCmdLineData[nBufferSize+1];
char pLogFile[nBufferSize+1];


};

#endif // SERVIZIO_H


<servizio.cpp>

#include "..\include\servizio.h"

static servizio* Service;

void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
Service->ServiceMain(dwArgc, lpszArgv);
}

void WINAPI ServiceHandler(DWORD fdwControl)
{
Service->ServiceHandler(fdwControl);
}






servizio::servizio()
{
//ctor
ProcessStarted = true;
}

servizio::~servizio()
{
//dtor
}




char *servizio::get_cmd()
{
return lpCmdLineData;
}

void servizio::set_cmd(char *b)
{
strcpy(lpCmdLineData, b);
}

char *servizio::get_pExeFile()
{
return pExeFile;
}

char *servizio::get_pServiceName()
{
return pServiceName;
}

void servizio::set_pServiceName(char *b)
{
strcpy(pServiceName, b);
}

char *servizio::get_pLogFile()
{
return pLogFile;
}

void servizio::set_pLogFile(char *b)
{
strcpy(pLogFile, b);
}

void servizio::ServiceMainProc()
{
::InitializeCriticalSection(&myCS);
// initialize variables for .exe and .log file names
char pModuleFile[nBufferSize+1];
DWORD dwSize = GetModuleFileName(NULL, pModuleFile, nBufferSize);
pModuleFile[dwSize] = 0;
if(dwSize>4 && pModuleFile[dwSize-4] == '.')
{
sprintf(pExeFile,"%s",pModuleFile);
pModuleFile[dwSize-4] = 0;
sprintf(pLogFile,"%s.log",pModuleFile);
}

set_pServiceName("servizio_test");

if(_stricmp("-i",get_cmd()) == 0 || _stricmp("-I",get_cmd()) == 0)
Install();
else if(_stricmp("-k",get_cmd()) == 0 || _stricmp("-K",get_cmd()) == 0)
KillService();
else if(_stricmp("-u",get_cmd()) == 0 || _stricmp("-U",get_cmd()) == 0)
UnInstall();
else if(_stricmp("-s",get_cmd()) == 0 || _stricmp("-S",get_cmd()) == 0)
RunService();
else
ExecuteSubProcess();
}

void servizio::Install()
{
SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (schSCManager==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenSCManager failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
SC_HANDLE schService = CreateService
(
schSCManager, /* SCManager database */
get_pServiceName(), /* name of service */
get_pServiceName(), /* service name to display */
SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROC ESS , /* service type */
SERVICE_AUTO_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
get_pExeFile(), /* service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no dependencies */
NULL, /* LocalSystem account */
NULL
); /* no password */
if (schService==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "Failed to create service %s, error code = %d\n", get_pServiceName(), nError);
WriteLog(pTemp);
}
else
{
char pTemp[121];
sprintf(pTemp, "Service %s installed\n", get_pServiceName());
WriteLog(pTemp);
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
}

void servizio::UnInstall()
{
SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (schSCManager==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenSCManager failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
SC_HANDLE schService = OpenService( schSCManager, get_pServiceName(), SERVICE_ALL_ACCESS);
if (schService==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenService failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
if(!DeleteService(schService))
{
char pTemp[121];
sprintf(pTemp, "Failed to delete service %s\n", get_pServiceName());
WriteLog(pTemp);
}
else
{
char pTemp[121];
sprintf(pTemp, "Service %s removed\n",get_pServiceName());
WriteLog(pTemp);
}
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
DeleteFile(get_pLogFile());
}

void servizio::WriteLog(char* pMsg)
{
// write error or other information into log file
::EnterCriticalSection(&myCS);
try
{
SYSTEMTIME oT;
::GetLocalTime(&oT);
FILE* pLog = fopen(get_pLogFile(),"a");
fprintf(pLog,"%02d/%02d/%04d, %02d:%02d:%02d\n %s",oT.wMonth,oT.wDay,oT.wYear,oT.wHour,oT.wMinute,oT .wSecond,pMsg);
fclose(pLog);
} catch(...) {}
::LeaveCriticalSection(&myCS);
}

bool servizio::KillService()
{
// kill service with given name
SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (schSCManager==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenSCManager failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
// open the service
SC_HANDLE schService = OpenService( schSCManager, get_pServiceName(), SERVICE_ALL_ACCESS);
if (schService==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenService failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
// call ControlService to kill the given service
SERVICE_STATUS status;
if(ControlService(schService,SERVICE_CONTROL_STOP,&status))
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return TRUE;
}
else
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "ControlService failed, error code = %d\n", nError);
WriteLog(pTemp);
}
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
return FALSE;
}

bool servizio::RunService()
{
// run service with given name
SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (schSCManager==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenSCManager failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
// open the service
SC_HANDLE schService = OpenService( schSCManager, get_pServiceName(), SERVICE_ALL_ACCESS);
if (schService==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "OpenService failed, error code = %d\n", nError);
WriteLog(pTemp);
}
else
{
// call StartService to run the service
if(StartService(schService, 0, (const char**)NULL))
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return TRUE;
}
else
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "StartService failed, error code = %d\n", nError);
WriteLog(pTemp);
}
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
return FALSE;
}


void servizio::ExecuteSubProcess()
{

lpServiceStartTable[0].lpServiceName = get_pServiceName();
lpServiceStartTable[0].lpServiceProc = ::ServiceMain;
lpServiceStartTable[1].lpServiceName = NULL;
lpServiceStartTable[1].lpServiceProc = NULL;

if(!StartServiceCtrlDispatcher(lpServiceStartTable ))
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "StartServiceCtrlDispatcher failed, error code = %d\n", nError);
WriteLog(pTemp);
}
::DeleteCriticalSection(&myCS);

WriteLog("sono partito\n");


}


void servizio::ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
DWORD status = 0;
DWORD specificError = 0xfffffff;

ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;

hServiceStatusHandle = RegisterServiceCtrlHandler(get_pServiceName(), ::ServiceHandler);
if (hServiceStatusHandle==0)
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "RegisterServiceCtrlHandler failed, error code = %d\n", nError);
WriteLog(pTemp);
return;
}

// Initialization complete - report running status
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
if(!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "SetServiceStatus failed, error code = %d\n", nError);
WriteLog(pTemp);
}

ExecuteSubProcess();
}


void servizio::ServiceHandler(DWORD fdwControl)
{
switch(fdwControl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
ProcessStarted = FALSE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
// terminate all processes started by this service before shutdown
break;
case SERVICE_CONTROL_PAUSE:
ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
//default:
//if(fdwControl>=128&&fdwControl<256)
//{
// ExecuteSubProcess();
//}
//else
//{
// char pTemp[121];
// sprintf(pTemp, "Unrecognized opcode %d\n", fdwControl);
// WriteLog(pTemp);
//}
};
if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
{
long nError = GetLastError();
char pTemp[121];
sprintf(pTemp, "SetServiceStatus failed, error code = %d\n", nError);
WriteLog(pTemp);
}
}


<main.cpp>

#include "include\servizio.h"

//using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
servizio *s;
s = new servizio();
if(argc >= 2)
s->set_cmd(argv[1]);

s->ServiceMainProc();

//s->~servizio();

return 0;
}

oregon
03-12-2011, 13:40
Benvenuto ... devi usare i tag [CODE] quando posti il codice altrimenti non si capisce molto.

L'errore indicato è abbastanza generico.

Chiarisci cosa dovrebbe fare il servizio per capire il contesto e quale compilatore/IDE hai usato per generare lo "scheletro" del codice.

whitedemon
03-12-2011, 14:13
scusare se non ho usato il tag [CODE] la prossima volta lo utilizzerò senz'altro.. allora come IDE ho usato code::blocks in quanto lo trovo molto completo, per quanto riguarda lo scopo, avrei l'esigenza di creare un servizio che abbia una porta in ascolto quindi successivamente dovrei sfruttare anche i sockets... però la mia intenzione era quella di creare una classe da poter poi riutilizzare per ogni mia esigenza.... grazie mille per l'attenzione

oregon
03-12-2011, 14:38
Non uso codeblocks ma, rispetto al codice generato, tu cosa hai modificato? Quale tipo di progetto hai utilizzato?

whitedemon
03-12-2011, 14:41
ho creato un progetto vuoto e l'ho scritto da 0 io su base di vari codici trovati sul web... (con visual studio è troppo facile :P e poi sulla versione 2010 hanno tolto anche la possibilità di fare servizi nt in c++)

oregon
03-12-2011, 14:45
Originariamente inviato da whitedemon
con visual studio è troppo facile

Beh, anche scrivere codice sbagliato e farlo correggere al forum è troppo facile ... :madai!?:

whitedemon
03-12-2011, 14:49
eheh io ci sto provando da 3 settimane ma da sempre errore ecco perchè provo a chiedere aiuto.... cmq prima di creare la classe ho scritto lo stesso identico programma con le stesse funzioni ma non orientato ad oggetti e funziona perfettamente....volevo creare una classe solo perchè mi sembra un modo piu pulito di programmare

oregon
03-12-2011, 15:20
Guarda ... è impossibile seguire quello che hai copiato/incollato come un "collage" ...

Il main di un servizio lo puoi trovare qui

http://msdn.microsoft.com/en-us/library/windows/desktop/ms687416(v=vs.85).aspx

e l'esempio completo qui

http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx

Se vuoi scrivere un servizio NT, il consiglio veramente spassionato è di evitare codice C/C++ ma usare - molto più semplicemente - un servizio .NET

whitedemon
03-12-2011, 15:26
perchè dici che è meglio evitare il c/c++ e utilizzare .NET? Io non sono molto d'accordo su questa tua affermazione. Personalmente ho provato e ne ho fatti molti di servizi in VB.NET, certamente è piu facile, pero windows poi usa la memoria del computer come vuole lui -.- i servizi e programmi in generale scritti in .NET per la mia esperienza personale sono piu pesanti a livello di risorse sulla macchina che li ospita.

oregon
03-12-2011, 15:33
Originariamente inviato da whitedemon
pero windows poi usa la memoria del computer come vuole lui

E questo che vuol dire? E' una ovvietà ...


i servizi e programmi in generale scritti in .NET per la mia esperienza personale sono piu pesanti a livello di risorse sulla macchina che li ospita.

Non particolarmente di più, a parte la prima volta nel momento in cui il JIT trasforma il bytecode in codice nativo.

Loading