< P>从本机C++中,您需要: 打开服务控制管理器的句柄 使用服务控制管理器获取要控制的服务的服务句柄 向服务发送一个或多个控制代码,以及 关闭在步骤1和2中打开的手柄,c++,windows-services,servicecontroller,C++,Windows Services,Servicecontroller" /> < P>从本机C++中,您需要: 打开服务控制管理器的句柄 使用服务控制管理器获取要控制的服务的服务句柄 向服务发送一个或多个控制代码,以及 关闭在步骤1和2中打开的手柄,c++,windows-services,servicecontroller,C++,Windows Services,Servicecontroller" />

从C+向服务发送命令+; 我如何将命令发送到C++的Windows服务?等效的.NET代码为: ServiceController sc = new ServiceController("MyService"); sc.ExecuteCommand(255); 使用、参见.< /P> < P>从本机C++中,您需要: 打开服务控制管理器的句柄 使用服务控制管理器获取要控制的服务的服务句柄 向服务发送一个或多个控制代码,以及 关闭在步骤1和2中打开的手柄

从C+向服务发送命令+; 我如何将命令发送到C++的Windows服务?等效的.NET代码为: ServiceController sc = new ServiceController("MyService"); sc.ExecuteCommand(255); 使用、参见.< /P> < P>从本机C++中,您需要: 打开服务控制管理器的句柄 使用服务控制管理器获取要控制的服务的服务句柄 向服务发送一个或多个控制代码,以及 关闭在步骤1和2中打开的手柄,c++,windows-services,servicecontroller,C++,Windows Services,Servicecontroller,例如,此代码重新启动时间同步服务。首先,我为服务句柄创建一个包装类,以便在离开块时自动关闭它们 class CSC_HANDLE { public: CSC_HANDLE(SC_HANDLE h) : m_h(h) { } ~CSC_HANDLE() { ::CloseServiceHandle(m_h); } operator SC_HANDLE () { return m_h; } private: SC_HANDLE m_h; }; 然后,我打开服务控制管理器(使用)和我想要控制

例如,此代码重新启动时间同步服务。首先,我为服务句柄创建一个包装类,以便在离开块时自动关闭它们

class CSC_HANDLE
{
public:
 CSC_HANDLE(SC_HANDLE h) : m_h(h) { }
 ~CSC_HANDLE() { ::CloseServiceHandle(m_h); }
 operator SC_HANDLE () { return m_h; }
private:
 SC_HANDLE m_h;
};
然后,我打开服务控制管理器(使用)和我想要控制的服务。请注意,dwDesiredAccess参数to必须包含我要发送的每个控件的权限,否则相关控件功能将失败

BOOL RestartTimeService()
{
    CSC_HANDLE hSCM(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, GENERIC_READ));
    if (NULL == hSCM) return FALSE;

    CSC_HANDLE hW32Time(::OpenService(hSCM, L"W32Time", SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS));
    if (NULL == hW32Time) return FALSE;
要停止服务,我使用发送服务\u控制\u停止代码,然后检查返回值以确保命令成功。如果报告了除error\u SERVICE\u NOT\u ACTIVE之外的任何错误,我假设启动服务不会成功

    SERVICE_STATUS ss = { 0 };
    ::SetLastError(0);
    BOOL success = ::ControlService(hW32Time, SERVICE_CONTROL_STOP, &ss);
    if (!success)
    {
        DWORD le = ::GetLastError();
        switch (le)
        {
        case ERROR_ACCESS_DENIED:
        case ERROR_DEPENDENT_SERVICES_RUNNING:
        case ERROR_INVALID_HANDLE:
        case ERROR_INVALID_PARAMETER:
        case ERROR_INVALID_SERVICE_CONTROL:
        case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
        case ERROR_SERVICE_REQUEST_TIMEOUT:
        case ERROR_SHUTDOWN_IN_PROGRESS:
            return FALSE;

        case ERROR_SERVICE_NOT_ACTIVE:
        default:
            break;
        }
    }
指示服务停止后,我等待服务经理报告服务实际上已停止。此代码有两个潜在的bug,您可能希望针对生产代码更正这两个bug:

  • Sleep(1000)将挂起此线程上的消息循环,因此如果此函数将在UI线程上运行,则应使用另一种方法延迟执行。您可以使用构造适当的sleep with message循环
  • 从中返回的DWORD将最终归零;如果它在函数等待时结束,那么等待可能会比我预期的更早放弃

    DWORD waitstart(::GetTickCount());
    while (true)
    {
        ZeroMemory(&ss, sizeof(ss));
        ::QueryServiceStatus(hW32Time, &ss);
        if (SERVICE_STOPPED == ss.dwCurrentState) break;
        ::Sleep(1000);
        DWORD tick(::GetTickCount());
        if ((tick < waitstart) || (tick > (waitstart + 30000))) return FALSE;
    }
    

    下面是一个小程序,它将连接到一个名为“MYSERVICE”的服务,然后发送一个命令141(由该服务定义)

    //ServiceCommunicator.cpp:定义控制台应用程序的入口点。
    //
    #包括“stdafx.h”
    #包括
    #包括
    使用名称空间std;
    int main()
    {
    SC_手柄管理器手柄;
    SC_手柄服务手柄;
    服务状态控制参数;
    德沃德·雷特地位;
    managerHandle=OpenSCManager(NULL,NULL,泛型读取);
    if(NULL!=managerHandle)
    {
    serviceHandle=OpenService(managerHandle,L“MYSERVICE”,服务\用户定义\控制\服务\查询\状态);
    if(NULL!=serviceHandle)
    {
    库特
    
        success = ::StartService(hW32Time, 0, NULL);
        if (!success) return FALSE;
    
        return TRUE;
    }
    
    // ServiceCommunicator.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        SC_HANDLE managerHandle;
        SC_HANDLE serviceHandle;
    
        SERVICE_STATUS   controlParms;
        DWORD retStatus;
    
        managerHandle = OpenSCManager(NULL, NULL, GENERIC_READ);
        if (NULL != managerHandle)
        {
            serviceHandle = OpenService(managerHandle, L"MYSERVICE", SERVICE_USER_DEFINED_CONTROL | SERVICE_QUERY_STATUS);
    
            if (NULL != serviceHandle)
            {
                cout << "connected to Service" << endl;
                retStatus = ControlService(serviceHandle, 141, &controlParms);
    
                if (retStatus)
                {
                    //Get the return code from the service
                    cout << "For command 141, return code from service was " << controlParms.dwWin32ExitCode << endl;
                }
                else
                    cout << "Sending command 141 failed" << endl;
    
                CloseServiceHandle(serviceHandle);
            }
            else
            {
                cout << "could not connect to Service" << endl;
            }
    
            CloseServiceHandle(managerHandle);
        }
        else
        {
            cout << "could not open service manager" << endl;
        }
        return 0;
    }