StartServiceCtrlDispatcher don't can access 10

2019-06-03 02:12发布

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;
}

2条回答
Luminary・发光体
2楼-- · 2019-06-03 02:52

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 get ERROR_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 like

if (argc < 2)
{
  if (!StartServiceCtrlDispatcher(ServiceTable)) 
  {
    f = GetLastError();
  }
} 
else if (strcmp(argv[1], "install")
{
  InstallService();
}

and 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().

查看更多
放荡不羁爱自由
3楼-- · 2019-06-03 02:55

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:

SERVICE_TABLE_ENTRY DispatchTable[] = {
            { (LPTSTR)srvName.str().c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
            { NULL,NULL }
        };
StartServiceCtrlDispatcher(DispatchTable);

After: it uses the pointer to LPWSTR (16 bits), that is the type of data that need SERVICE_TABLE_ENTRYW and StartServiceCtrlDispatcherW:

SERVICE_TABLE_ENTRYW DispatchTable[] = {
            { (LPWSTR)srvName.str().c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
            { NULL,NULL }
        };
StartServiceCtrlDispatcherW(DispatchTable);

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.

查看更多
登录 后发表回答