Check if a services is installed using C

2019-02-28 10:38发布

问题:

I'm writing a C application which creates a Windows service. I'd like to check if the service is installed before trying to call the installation function, but I can't manage to find how to check it.

I've written the code above to try :

DWORD InstallMyService()
{
    char strDir[1024 + 1];
    SC_HANDLE schSCManager;
    SC_HANDLE schService;
    LPCTSTR lpszBinaryPathName;

    if (GetCurrentDirectory(1024, strDir) == 0)
    {
        aff_error("GetCurrentDirectory");
        return FALSE;
    }
    strcat(strDir, "\\"MY_SERVICE_BIN_NAME);
    if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
    {
        printf("Error OpenSCManager : %d\n", GetLastError());
        return FALSE;
    }
    lpszBinaryPathName = strDir;
    schService = CreateService(schSCManager, MY_SERVICE_NAME, MY_SERVICE_DESCRIPTOR,
                             SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
                             lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL);
    if (schService == NULL)
    {
        printf("Error CreateService : %d\n", GetLastError());
        return FALSE;
    }
    CloseServiceHandle(schService);
    return TRUE;
}

But this code does not detect if the service is still existing or not. Do someone have an idea of which function to call ? I found many posts talking about this, but not in C, only in C# or VB.

Thank you.

回答1:

A possibility would be to always attempt to CreateService() and if failure query GetLastError() and check if it is equal to ERROR_SERVICE_EXISTS:

SC_HANDLE service_handle = CreateService(...);
if (0 == service_handle)
{
    if (ERROR_SERVICE_EXISTS == GetLastError())
    {
        /* Handle service already exists. */
    }
    else
    {
        /* Handle failure. */
    }
}

This would require a slight change to your code from having two functions InstallService() and CheckService() to having one function (for example) EnsureServiceInstalled().

Or, you could use the OpenService() function, which will fail with GetLastError() code of ERROR_SERVICE_DOES_NOT_EXIST:

SC_HANDLE scm_handle = OpenSCManager(0, 0, GENERIC_READ);

if (scm_handle)
{
    SC_HANDLE service_handle = OpenService(scm_handle,
                                           "the-name-of-your-service",
                                           GENERIC_READ);
    if (!service_handle)
    {
        if (ERROR_SERVICE_DOES_NOT_EXIST != GetLastError())
        {
            fprintf(stderr,
                    "Failed to OpenService(): %d\n",
                    GetLastError());
        }
        else
        {
            /* Service does not exist. */
            fprintf(stderr, "Service does not exist.\n");
        }
    }
    else
    {
        fprintf(stderr, "Opened service.\n");
        CloseServiceHandle(service_handle);
    }

    CloseServiceHandle(scm_handle);
}
else
{
    fprintf(stderr,
            "Failed to OpenSCManager(): %d\n",
            GetLastError());
}


回答2:

If you need a yes / no answer whether a service is installed or note, use the following function:

bool IsServiceInstalled(LPWSTR ServiceName)
{
    bool serviceInstalled = false;
    SC_HANDLE scm_handle = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
    if (scm_handle)
    {
        SC_HANDLE service_handle = OpenService(scm_handle, ServiceName, SERVICE_INTERROGATE);
        if (service_handle != NULL)
        {
            wprintf(L"Service  Installed\n");
            serviceInstalled = true;
            CloseServiceHandle(service_handle);
        }
        else
        {
            wprintf(_T("OpenService failed - service not installed\n"));
        }
        CloseServiceHandle(scm_handle);
    }
    else
        wprintf(_T("OpenService couldn't open - service not installed\n"));

    return serviceInstalled;

}


回答3:

Try using QueryServiceStatusEx

See example here