¿cómo puedo enviar comandos a un servicio de Windows desde C++? NET equivalente es:Enviar comando al servicio de C++
ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(255);
¿cómo puedo enviar comandos a un servicio de Windows desde C++? NET equivalente es:Enviar comando al servicio de C++
ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(255);
De nativo de C++, tendrá que:
Por ejemplo, este código reinicia el servicio de sincronización de tiempo. Primero, creo una clase contenedora para los identificadores de servicio, para cerrarlos automáticamente al salir del bloque.
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;
};
Entonces, abro el Administrador de control de servicios (utilizando OpenSCManager()) y el servicio que desea controlar. Tenga en cuenta que el parámetro dwDesiredAccess a OpenService() debe incluir permisos para cada control que deseo enviar, o las funciones de control relevantes fallarán.
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;
Para detener el servicio, yo uso ControlService() para enviar el código SERVICE_CONTROL_STOP, y después comprobar el valor de retorno para asegurarse de que el comando tuvo éxito. Si se informa algún error que no sea ERROR_SERVICE_NOT_ACTIVE, supongo que el inicio del servicio no tendrá éxito.
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;
}
}
Después de instruir el servicio de parar, espero el gerente de servicio para informar que el servicio es, de hecho, se detuvo. Este código tiene dos errores potenciales, que tal vez desee para corregir el código de producción:
El DWORD devuelto desde GetTickCount() se ajustará eventualmente a cero; si se enrolla mientras esta función está esperando, la espera puede ceder antes de lo previsto.
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;
}
Por último, sabiendo que el servicio está en un estado detenido, me llaman StartService() ejecutarlo de nuevo.
success = ::StartService(hW32Time, 0, NULL);
if (!success) return FALSE;
return TRUE;
}
Se utiliza ControlService, ver Service Control Requests.