gpt4 book ai didi

c++ - 从 C++ 向服务发送命令

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:27:26 25 4
gpt4 key购买 nike

如何从 C++ 向 Windows 服务发送命令?等效的 .NET 代码是:

ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(255);

最佳答案

从 native C++,您将需要:

  1. 打开服务控制管理器的句柄,
  2. 使用服务控制管理器获取您要控制的服务的服务句柄,
  3. 向服务发送一个或多个控制代码,以及
  4. 关闭在步骤 1 和 2 中打开的句柄。

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

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

然后,我打开服务控制管理器(使用 OpenSCManager() )和我想要控制的服务。注意 OpenService() 的 dwDesiredAccess 参数必须包含我要发送的每个控件的权限,否则相关的控件功能将失败。

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;

要停止服务,我使用 ControlService()发送 SERVICE_CONTROL_STOP 代码,然后检查返回值以确保命令成功。如果报告 ERROR_SERVICE_NOT_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;
}
}

指示服务停止后,我等待服务管理器报告服务实际上已停止。此代码有两个潜在的错误,您可能希望针对生产代码更正这些错误:

  1. Sleep(1000) 将暂停此线程上的消息循环,因此如果此函数将在 UI 线程上运行,则应使用其他方法来延迟执行。您可以使用 MsgWaitForMultipleObjectsEx() 构造一个合适的 sleep-with-message-loop| .
  2. GetTickCount() 返回的 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;
    }

最后,知道服务处于停止状态,我调用 StartService()再次运行它。

    success = ::StartService(hW32Time, 0, NULL);
if (!success) return FALSE;

return TRUE;
}

关于c++ - 从 C++ 向服务发送命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1592930/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com