Couldn't find any example on the net, so here it goes - it installs / uninstalls itself when passed correct arguments. --svc, to run code.
main.h:
Code: Select all
SERVICE_STATUS svcStatus;
SERVICE_STATUS_HANDLE svcStatusHnd;
void WINAPI svcStart(DWORD argc, LPTSTR *argv);
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ "SampleService", &svcStart },
{ NULL, NULL }
};
SC_HANDLE m_globalSCM;
void WINAPI svcHandler(DWORD opcode);
class MainApp: public wxApp
{
private:
bool openSCM(void);
void closeSCM(void);
bool isInstalled(void);
void install(void);
void uninstall(void);
public:
virtual bool OnInit();
};
Code: Select all
IMPLEMENT_APP_NO_MAIN(MainApp)
HINSTANCE g_hInstance;
HINSTANCE g_hPrevInstance;
wxCmdLineArgType g_lpCmdLine;
int g_nCmdShow;
extern "C" int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
wxCmdLineArgType lpCmdLine,
int nCmdShow)
{
if(strstr(lpCmdLine, "--svc")==NULL) {
return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
} else {
g_hInstance = hInstance;
g_hPrevInstance = hPrevInstance;
g_lpCmdLine = lpCmdLine;
g_nCmdShow = nCmdShow;
StartServiceCtrlDispatcher(dispatchTable);
}
}
bool MainApp::OnInit()
{
wxString usage = "--install\n--uninstall";
if(argc!=2) {
wxMessageDialog(NULL, usage, "SampleService", wxOK).ShowModal();
return FALSE;
}
wxString command = argv[1];
if(command=="--svc") {
// INIT THE REAL SERVICE HERE AND LET THE MAIN LOOP RUN
return TRUE;
} else if(command=="--install") {
if(isInstalled()) {
wxMessageDialog(NULL, "SampleService already installed", "SampleService", wxOK).ShowModal();
} else {
install();
}
} else if(command=="--uninstall") {
if(!isInstalled()) {
wxMessageDialog(NULL, "SampleService was not installed.", "SampleService", wxOK).ShowModal();
} else {
uninstall();
}
} else {
wxMessageDialog(NULL, usage, "SampleService", wxOK).ShowModal();
}
return FALSE;
}
bool MainApp::isInstalled(void) {
bool found;
openSCM();
SC_HANDLE svc = OpenService(
m_globalSCM,
TEXT("SampleService"),
SERVICE_ALL_ACCESS);
if(svc) {
found=true;
CloseServiceHandle(svc);
} else found=false;
closeSCM();
return found;
}
bool MainApp::openSCM(void) {
m_globalSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == m_globalSCM) {
wxMessageDialog(NULL, wxString::Format("openSCM error %d", GetLastError()), "SampleService", wxOK).ShowModal();
return FALSE;
} else
return TRUE;
}
void MainApp::closeSCM(void) {
CloseServiceHandle(m_globalSCM);
}
void MainApp::install(void) {
openSCM();
SC_HANDLE schService = CreateService(
m_globalSCM,
TEXT("SampleService"), // name of service
"SampleService",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // remove interactive if not using gui
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
wxString::Format("\"%s\" --svc", argv[0]),
NULL,
NULL,
NULL,
NULL,
NULL);
if(schService==NULL)
wxMessageDialog(NULL, wxString::Format("createSvc error %d", GetLastError()), "SampleService", wxOK).ShowModal();
else
wxMessageDialog(NULL, "SampleService installed.", "SampleService", wxOK).ShowModal();
closeSCM();
}
void MainApp::uninstall(void) {
openSCM();
SC_HANDLE svc = OpenService(
m_globalSCM,
TEXT("SampleService"),
SERVICE_ALL_ACCESS);
SERVICE_STATUS status;
ControlService(svc, SERVICE_CONTROL_STOP, &status);
if(!DeleteService(svc))
wxMessageDialog(NULL, wxString::Format("deleteSvc error %d", GetLastError()), "SampleService", wxOK).ShowModal();
else
wxMessageDialog(NULL, "SampleService uninstalled.", "SampleService", wxOK).ShowModal();
CloseServiceHandle(svc);
closeSCM();
}
void WINAPI svcStart(DWORD argc, LPTSTR *argv) {
svcStatusHnd = RegisterServiceCtrlHandler("SampleService", &svcHandler);
if(!svcStatusHnd) {
MessageBox(NULL, "svcHandler error", "SampleService", MB_OK);
}
svcStatus.dwServiceType = SERVICE_WIN32;
svcStatus.dwCurrentState = SERVICE_START_PENDING;
svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
svcStatus.dwWin32ExitCode = 0;
svcStatus.dwServiceSpecificExitCode = 0;
svcStatus.dwCurrentState = SERVICE_RUNNING;
svcStatus.dwCheckPoint = 0;
svcStatus.dwWaitHint = 0;
if(SetServiceStatus(svcStatusHnd, &svcStatus))
wxEntry(g_hInstance, g_hPrevInstance, g_lpCmdLine, g_nCmdShow);
return;
}
void WINAPI svcHandler (DWORD opcode) {
DWORD status;
switch(opcode)
{
case SERVICE_CONTROL_PAUSE:
svcStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
svcStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
svcStatus.dwWin32ExitCode = 0;
svcStatus.dwCurrentState = SERVICE_STOPPED;
svcStatus.dwCheckPoint = 0;
svcStatus.dwWaitHint = 0;
if (!SetServiceStatus (svcStatusHnd, &svcStatus))
{
status = GetLastError();
MessageBox(NULL, "svcStatusStop error", "SampleService", MB_OK);
}
// exit prog
return;
case SERVICE_CONTROL_INTERROGATE:
break;
}
if (!SetServiceStatus (svcStatusHnd, &svcStatus))
{
status = GetLastError();
// error msg
}
return;
}