Windows中注册并启动服务

一、Windows服务相关函数

(1).OpenSCManager函数

OpenSCManager 函数用于打开一个服务控制管理器数据库(Service Control Manager Database)。服务控制管理器是 Windows 操作系统中的一个组件,用于管理系统上运行的服务。通过服务控制管理器,您可以创建、删除、启动、停止和查询服务,还可以获取有关服务的信息。

以下是 OpenSCManager 函数的基本介绍和使用方法:

SC_HANDLE OpenSCManager(
  LPCWSTR lpMachineName,
  LPCWSTR lpDatabaseName,
  DWORD   dwDesiredAccess
);  

参数说明:

  • lpMachineName:要连接的远程计算机的名称。如果要连接本地计算机,可以设置为 NULL
  • lpDatabaseName:要打开的数据库名称。通常为 "Services",用于指定对服务控制管理器数据库(Service Control Manager Database)的完全访问权限。服务控制管理器允许您管理系统上运行的服务,包括创建、删除、启动、停止和查询服务,以及获取有关服务的信息。
  • dwDesiredAccess:所需的访问权限。例如,SC_MANAGER_ALL_ACCESS 表示连接到服务控制管理器。

返回值:

  • 如果成功,返回一个类型为 SC_HANDLE 的服务控制管理器句柄。
  • 如果失败,返回 NULL。您可以使用 GetLastError 函数来获取更多错误信息。

使用示例:

#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL,SC_MANAGER_ALL_ACCESS);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    // 在此处进行操作,例如创建、启动、停止服务等

    CloseServiceHandle(scm);

    return 0;
}

在上述示例中,使用 OpenSCManager 打开了服务控制管理器数据库。然后可以在获取到的句柄 scm 上执行各种操作,如创建、启动、停止服务等。完成操作后,不要忘记调用 CloseServiceHandle 关闭服务控制管理器句柄。 

(2).CreateService函数

CreateService 函数用于在服务控制管理器数据库中创建一个新的服务。服务控制管理器是 Windows 操作系统的一个组件,用于管理系统上运行的服务。通过 CreateService 函数,您可以指定服务的各种属性,如名称、显示名称、类型、启动类型、二进制路径等。

以下是 CreateService 函数的基本介绍和使用方法:

SC_HANDLE CreateService(
  SC_HANDLE hSCManager,
  LPCWSTR   lpServiceName,
  LPCWSTR   lpDisplayName,
  DWORD     dwDesiredAccess,
  DWORD     dwServiceType,
  DWORD     dwStartType,
  DWORD     dwErrorControl,
  LPCWSTR   lpBinaryPathName,
  LPCWSTR   lpLoadOrderGroup,
  LPDWORD   lpdwTagId,
  LPCWSTR   lpDependencies,
  LPCWSTR   lpServiceStartName,
  LPCWSTR   lpPassword
);

参数说明:

  • hSCManager:打开的服务控制管理器句柄,通常是由 OpenSCManager 函数获得的。
  • lpServiceName:服务的名称,用于标识服务。这个名称必须是唯一的。
  • lpDisplayName:服务的显示名称,用户可读的名称。
  • dwDesiredAccess:对服务的访问权限。通常使用 SERVICE_ALL_ACCESS 或其他适当的访问权限常量。
  • dwServiceType:服务类型,如 SERVICE_WIN32_OWN_PROCESS
  • dwStartType:启动类型,如 SERVICE_AUTO_START
  • dwErrorControl:错误控制,如 SERVICE_ERROR_NORMAL
  • lpBinaryPathName:可执行文件的路径,包括参数。这个文件将作为服务的主体运行。
  • 其他参数用于指定组、标签、依赖项、服务启动用户名等。对于大多数情况,您可以设置为 NULL

返回值:

  • 如果成功,返回一个类型为 SC_HANDLE 的服务句柄。
  • 如果失败,返回 NULL。您可以使用 GetLastError 函数来获取更多错误信息。

使用示例:

#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    const wchar_t *serviceName = L"MyServiceName";
    const wchar_t *serviceDisplayName = L"My Service Display Name";
    const wchar_t *binaryPath = L"C:\\Path\\To\\Your\\Service.exe"; // 替换为实际的可执行文件路径

    SC_HANDLE service = CreateService(
        scm,
        serviceName,
        serviceDisplayName,
        SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_AUTO_START,
        SERVICE_ERROR_NORMAL,
        binaryPath,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
    );

    if (service == NULL) {
        std::cerr << "Failed to create service." << std::endl;
        CloseServiceHandle(scm);
        return 1;
    }

    std::cout << "Service created successfully." << std::endl;

    CloseServiceHandle(service);
    CloseServiceHandle(scm);

    return 0;
}

在上述示例中,使用 CreateService 函数创建了一个新的服务。请注意,要创建服务通常需要管理员权限。同时,确保在实际应用中提供正确的参数,如服务名称、显示名称、二进制路径等。完成操作后,不要忘记调用 CloseServiceHandle 关闭服务句柄和服务控制管理器句柄。  

(3).OpenService函数

OpenService 函数用于打开一个现有的服务,以便您可以执行对该服务的操作,如启动、停止、查询状态等。您需要提供服务所在的服务控制管理器数据库的句柄以及服务的名称。

以下是 OpenService 函数的基本介绍和使用方法:

SC_HANDLE OpenService(
  SC_HANDLE hSCManager,
  LPCWSTR   lpServiceName,
  DWORD     dwDesiredAccess
);

参数说明:

  • hSCManager:已经打开的服务控制管理器句柄,通常是通过 OpenSCManager 函数获取的。
  • lpServiceName:服务的名称,您要打开的现有服务的标识符。
  • dwDesiredAccess:您希望获取的服务访问权限。通常使用 SERVICE_ALL_ACCESS 或其他适当的访问权限常量。

返回值:

  • 如果成功,返回一个类型为 SC_HANDLE 的服务句柄。
  • 如果失败,返回 NULL。您可以使用 GetLastError 函数来获取更多错误信息。

使用示例:

#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    const wchar_t *serviceName = L"MyServiceName";

    SC_HANDLE service = OpenService(scm, serviceName, SERVICE_ALL_ACCESS);
    if (service == NULL) {
        std::cerr << "Failed to open service." << std::endl;
        CloseServiceHandle(scm);
        return 1;
    }

    // 在此处进行操作,如查询服务状态、启动、停止等

    CloseServiceHandle(service);
    CloseServiceHandle(scm);

    return 0;
}

(4).QueryServiceStatus函数

QueryServiceStatus 函数用于查询指定服务的当前状态。您可以使用这个函数来获取有关服务的信息,如服务是否正在运行、服务的当前状态等。

以下是 QueryServiceStatus 函数的基本介绍和使用方法:

BOOL QueryServiceStatus(
  SC_HANDLE      hService,
  LPSERVICE_STATUS lpServiceStatus
);

参数说明:

  • hService:要查询状态的服务句柄,通常是通过 OpenService 函数获得的。
  • lpServiceStatus:一个指向 SERVICE_STATUS 结构的指针,用于接收查询到的服务状态信息。

返回值:

  • 如果成功,返回非零值 (TRUE)。
  • 如果失败,返回零 (FALSE)。您可以使用 GetLastError 函数来获取更多错误信息。

SERVICE_STATUS 结构包含了有关服务状态的信息,包括当前状态、进程 ID、计数器等。以下是结构的一些字段:

typedef struct _SERVICE_STATUS {
  DWORD dwServiceType;
  DWORD dwCurrentState;
  DWORD dwControlsAccepted;
  DWORD dwWin32ExitCode;
  DWORD dwServiceSpecificExitCode;
  DWORD dwCheckPoint;
  DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;
  • dwServiceType:服务类型,如 SERVICE_WIN32_OWN_PROCESS
  • dwCurrentState:当前服务状态,如 SERVICE_RUNNING
  • dwControlsAccepted:接受的控制代码,如 SERVICE_ACCEPT_STOP
  • dwWin32ExitCode:Win32 退出代码。
  • dwServiceSpecificExitCode:服务特定的退出代码。
  • dwCheckPoint:用于报告服务状态检查点。
  • dwWaitHint:等待时间估计。

使用示例:

#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    const wchar_t *serviceName = L"MyServiceName";

    SC_HANDLE service = OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
    if (service == NULL) {
        std::cerr << "Failed to open service." << std::endl;
        CloseServiceHandle(scm);
        return 1;
    }

    SERVICE_STATUS serviceStatus;
    if (QueryServiceStatus(service, &serviceStatus)) {
        if (serviceStatus.dwCurrentState == SERVICE_RUNNING) {
            std::cout << "Service is running." << std::endl;
        } else if (serviceStatus.dwCurrentState == SERVICE_STOPPED) {
            std::cout << "Service is stopped." << std::endl;
        } else {
            std::cout << "Service is in another state." << std::endl;
        }
    } else {
        std::cerr << "Failed to query service status." << std::endl;
    }

    CloseServiceHandle(service);
    CloseServiceHandle(scm);

    return 0;
}

5.ControlService函数

ControlService 函数用于向一个已经打开的服务发送控制代码,从而控制服务的行为,例如启动、停止、暂停、恢复等。  

以下是 ControlService 函数的基本介绍和使用方法:  

BOOL ControlService(
  SC_HANDLE        hService,
  DWORD            dwControl,
  LPSERVICE_STATUS lpServiceStatus
);

参数说明:

  • hService:已经打开的服务句柄,通常是通过 OpenService 函数获取的。
  • dwControl:控制代码,指定要发送的控制操作,如 SERVICE_CONTROL_STOP 用于停止服务。
  • lpServiceStatus:一个指向 SERVICE_STATUS 结构的指针,用于接收服务状态信息。

返回值:

  • 如果成功,返回非零值 (TRUE)。
  • 如果失败,返回零 (FALSE)。您可以使用 GetLastError 函数来获取更多错误信息。

dwControl 参数可以是以下值之一,表示不同的控制操作:

  • SERVICE_CONTROL_CONTINUE:继续暂停的服务。
  • SERVICE_CONTROL_INTERROGATE:查询服务状态。
  • SERVICE_CONTROL_PAUSE:暂停服务。
  • SERVICE_CONTROL_STOP:停止服务。
  • ... 等其他控制代码。
#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    const wchar_t *serviceName = L"MyServiceName";

    SC_HANDLE service = OpenService(scm, serviceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
    if (service == NULL) {
        std::cerr << "Failed to open service." << std::endl;
        CloseServiceHandle(scm);
        return 1;
    }

    SERVICE_STATUS serviceStatus;
    if (ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus)) {
        std::cout << "Service control request sent successfully." << std::endl;
    } else {
        std::cerr << "Failed to send service control request." << std::endl;
    }

    CloseServiceHandle(service);
    CloseServiceHandle(scm);

    return 0;
}

6.StartService函数

StartService 函数用于启动一个已经打开的服务。您可以使用这个函数来启动服务,将其从停止状态切换为运行状态。  

以下是 StartService 函数的基本介绍和使用方法:

BOOL StartService(
  SC_HANDLE    hService,
  DWORD        dwNumServiceArgs,
  LPCTSTR      *lpServiceArgVectors
);

参数说明:

  • hService:已经打开的服务句柄,通常是通过 OpenService 函数获取的。
  • dwNumServiceArgs:提供给服务的参数个数。
  • lpServiceArgVectors:指向参数数组的指针,这个参数可以为 NULL

返回值:

  • 如果成功,返回非零值 (TRUE)。
  • 如果失败,返回零 (FALSE)。您可以使用 GetLastError 函数来获取更多错误信息。

使用示例:

#include <Windows.h>
#include <iostream>

int main() {
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (scm == NULL) {
        std::cerr << "Failed to open service manager." << std::endl;
        return 1;
    }

    const wchar_t *serviceName = L"MyServiceName";

    SC_HANDLE service = OpenService(scm, serviceName, SERVICE_START);
    if (service == NULL) {
        std::cerr << "Failed to open service." << std::endl;
        CloseServiceHandle(scm);
        return 1;
    }

    if (StartService(service, 0, NULL)) {
        std::cout << "Service started successfully." << std::endl;
    } else {
        std::cerr << "Failed to start service." << std::endl;
    }

    CloseServiceHandle(service);
    CloseServiceHandle(scm);

    return 0;
}

 二、注册并启动服务的完整示例

#include <Windows.h>
#include <iostream>

BOOL start_monitor_service(const char* service_name, const char* service_display_name,  const char* service_path)
{
    //打开服务管理器
    SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (scm == NULL) {
        std::cout << "Failed to open service manager:" << GetLastError() << std::endl;

        return FALSE;
    }

    wchar_t w_service_name[256] = { 0 };
    mbstowcs(w_service_name, service_name, strlen(service_name) + 1);

    wchar_t w_service_display_name[256] = { 0 };
    mbstowcs(w_service_display_name, service_display_name, strlen(service_display_name) + 1);

    wchar_t w_service_path[256] = { 0 };
    mbstowcs(w_service_path, service_path, strlen(service_path) + 1);

    //注册服务
    SC_HANDLE create_service = CreateService(
        scm,
        w_service_name,
        w_service_display_name,
        SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_AUTO_START,
        SERVICE_ERROR_NORMAL,
        w_service_path,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
    );
    if (create_service == NULL) {
        std::cout << "Failed to create service:" << GetLastError() << std::endl;
        CloseServiceHandle(scm);

        return FALSE;
    }

    //打开要启动的服务
    SC_HANDLE open_service = OpenService(scm, w_service_name, SERVICE_START);
    if (open_service == NULL) {
        std::cout << "Failed to open service" << GetLastError() << std::endl;
        CloseServiceHandle(create_service);
        CloseServiceHandle(scm);

        return FALSE;
    }

    //启动服务
    if (!StartService(open_service, 0, NULL)) {
        std::cout << "Failed to start service:" << GetLastError() << std::endl;
        CloseServiceHandle(open_service);
        CloseServiceHandle(create_service);
        CloseServiceHandle(scm);

        return FALSE;
    }

    std::cout << "Service registered successfully" << std::endl;

    //查询服务状态
    SERVICE_STATUS service_status;
    if (!QueryServiceStatus(open_service, &service_status)) {
        std::cout << "Failed to query service status:" << GetLastError() << std::endl;
        CloseServiceHandle(open_service);
        CloseServiceHandle(create_service);
        CloseServiceHandle(scm);

        return false;
    }

    //判断服务的运行状态
    if (service_status.dwCurrentState == SERVICE_RUNNING) {
        //停止服务
        if (ControlService(open_service, SERVICE_CONTROL_STOP, &service_status)) {
            std::cout << "Service stoping..." << std::endl;

            /*
            SERVICE_STOP_PENDING:这个常量表示服务正在停止过程中,但尚未完全停止。当您发送停止命令给服务时,
            服务可能需要一些时间来完成清理和停止操作,这时服务状态会被设置为 SERVICE_STOP_PENDING。         
            */
            //等待服务停止
            while (service_status.dwCurrentState == SERVICE_STOP_PENDING) {
                Sleep(1000);
                if (!QueryServiceStatus(open_service, &service_status)) {
                    std::cout << "Failed to query service status." << std::endl;
                    break;
                }
            }

            /*
            SERVICE_STOPPED:这个常量表示服务已经完全停止。当服务停止操作完成后,服务状态会被设置为 SERVICE_STOPPED。
            */
            if (service_status.dwCurrentState == SERVICE_STOPPED) {
                std::cout << "Service stopped successfully." << std::endl;
            }
            else {
                std::cerr << "Failed to stop service." << std::endl;
            }
        }
    }
    
    CloseServiceHandle(open_service);
    CloseServiceHandle(create_service);
    CloseServiceHandle(scm);

    return true;
}

 

posted @ 2023-08-31 11:55  TechNomad  阅读(823)  评论(2编辑  收藏  举报