发送命令的服务从C++
-
22-09-2019 - |
题
怎么我可以发送命令Windows服务从C++?相当。净码是:
ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(255);
解决方案
从地C++,你会需要:
- 打开一个处理的业务控制经理,
- 使用该服务的控制管理中心获得的服务处理对于你想要的服务来控制,
- 发送控制代码或密码服务,并且
- 关处理建于步骤1和2。
例如,这种代码重新启动的时间同步服务。第一,我创建了一个包装类的服务处理,关闭他们自动离开时的区块。
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())和服务,我要到控制。注意dwDesiredAccess参数 OpenService() 必须包括的权限,每个控制我想送,或相关的控制功能将失败。
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;
}
}
之后,指示的服务停止,我等服务管理报告,该服务是在事实上停止。这个代码有两个潜在的错误,你可能希望纠正生产码:
- 睡眠(1000)将暂停息的循环,在这个线程,因此应使用另外的方法延迟执行,如果这种功能将运行在UI线。你可以构造一个适合睡觉-有消息循环使用 MsgWaitForMultipleObjectsEx().
在双回来 GetTickCount() 将围绕以零的最终;如果它环绕,而这功能等待,等待可能放弃早于我的目的。
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;
}
其他提示
您使用 ControlService ,看服务控制请求的。
这里是一个小程序,其将连接到一个被称为“MYSERVICE”的服务,然后发送命令141(其由服务定义)
// 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;
}
不隶属于 StackOverflow