I write on c++ service , but have error, and don't can fixed it.
my service main function
int main (int argc, TCHAR *argv[])
{DWORD f;
for(int i=0;i<113;i++)
f = GetLastError();
servicePath = LPTSTR(argv[0]);
OutputDebugString(_T("My Sample Service: Main: Entry"));
//InstallService();
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{NULL, NULL}
};
// StartService();
if(!StartServiceCtrlDispatcher(ServiceTable)) {
f = GetLastError();
//addLogMessage("Error: StartServiceCtrlDispatcher");
} else if( memcmp(argv[argc-1],"install",7)) {
InstallService();
} else if( memcmp(argv[argc-1],"remove",6)) {
RemoveService();
} else if( memcmp(argv[argc-1],"start",5)) {
StartService();
} else if( memcmp(argv[argc-1],"stop",4)) {
// StopService();
}
// StopService();
OutputDebugString(_TEXT("My Sample Service: Main: Exit"));
return 0;
}
Where I debug my programm with command line arguments (service_path and action) on StartServiceCtrlDispatcher every time return 1063 error. Visual Studio I run under Administrator. Where I write wrong code, please help.
UPDATE
VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv)
{
DWORD Status = E_FAIL;
OutputDebugString(_T("My Sample Service: ServiceMain: Entry"));
g_StatusHandle = RegisterServiceCtrlHandler (SERVICE_NAME, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
}
// Tell the service controller we are starting
ZeroMemory (&g_ServiceStatus, sizeof (g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
/*
* Perform tasks neccesary to start the service here
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));
// Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
// Tell the service controller we are started
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
// Start the thread that will perform the main task of the service
HANDLE hThread = CreateThread (NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
OutputDebugString(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));
// Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject (hThread, INFINITE);
OutputDebugString(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));
/*
* Perform any cleanup tasks
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));
CloseHandle (g_ServiceStopEvent);
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
OutputDebugString(_T("My Sample Service: ServiceMain: Exit"));
return;
}
VOID WINAPI ServiceCtrlHandler (DWORD CtrlCode)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Entry"));
switch (CtrlCode)
{
case SERVICE_CONTROL_STOP :
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SERVICE_CONTROL_STOP Request"));
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;
/*
* Perform tasks neccesary to stop the service here
*/
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 4;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SetServiceStatus returned error"));
}
// This will signal the worker thread to start shutting down
SetEvent (g_ServiceStopEvent);
break;
default:
break;
}
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Exit"));
}
DWORD WINAPI ServiceWorkerThread (LPVOID lpParam)
{
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));
main2();
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return ERROR_SUCCESS;
}
You can only call
StartServiceCtrlDispatcher
when your process was started by the Service Control Manager, i.e., when it is actually running as a service. When called from any other context, you will getERROR_FAILED_SERVICE_CONTROLLER_CONNECT
(1063).From the looks of your code, you should only be calling
StartServiceControlDispatcher
if no command-line argument was passed, e.g., something likeand so on.
There are also some other problems with your main() function, most notably:
The wrong signature; argv[] is char, not TCHAR
Casting argv[0] to TCHAR
A loop which calls GetLastError for no reason, 114 times
The use of memcmp instead of strcmp
I didn't look at ServiceMain().
it happen when the service is installed over windows 8, or later, of 64 bits and is invoked the method StartServiceCtrlDispatcher which will invoke the Main entry point. But the method StartServiceCtrlDispatcher works with pointer of 8 bits.
So, the solution is to use the function StartServiceCtrlDispatcherW which works with pointers of 16 bits, for example:
Before: it uses the pointer to LPTSTR (8 bits), that is the type of data that need SERVICE_TABLE_ENTRY and StartServiceCtrlDispatcher:
After: it uses the pointer to LPWSTR (16 bits), that is the type of data that need SERVICE_TABLE_ENTRYW and StartServiceCtrlDispatcherW:
Conclusion:
Use the wide string (16 bits per char) and the functions of StartServiceCtrlDispatcherW and SERVICE_TABLE_ENTRYW Type instead of StartServiceCtrlDispatcher and SERVICE_TABLE_ENTRY.