c - 如何正确使用 SetServiceStatus 告诉 Windows 我的服务正在停止?

原文 标签 c windows-services

对示例的长度感到抱歉,但为了获得服务的所有必需组件,它必须这么长。

在这里使用其他人的帮助,我设法获得了一个干净启动的服务,但现在它不会干净地停止。

在第一次尝试快速停止它时会出现错误

Could not stop the My service service on local computer
The service did not return an error. This could be an internal Windows error or an internal service error
If the problem persists, contact your system administrator

并且服务继续运行,即使在 sleep 循环需要 5 分钟之后也是如此。

在第二次尝试停止时,任务管理器显示进程立即停止,但服务管理器需要很长时间才能给出错误
Could not stop the My service service on local computer
Error 1053: The service did not respond to the start or control request in a timely fashion.

这是源代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <windows.h>
#include <winsvc.h>
#include <time.h>

#define MY_SVC_NAME "My service"
#define THE_PROG "\"C:\\Program Files\\My software\\bin\\The Prog.exe\""
#define SLEEP_TIME 300000

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void WINAPI ServiceMain(DWORD argc, LPSTR argv);
void WINAPI ControlHandler(DWORD request);
void InitService();


int cont_running = 1;

DWORD WINAPI ServiceHandlerProc(DWORD ControlCode, DWORD a, void *b, void *c)
{
  switch (ControlCode) {
  case SERVICE_CONTROL_STOP :
    cont_running = 0;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCurrentState  = SERVICE_STOP_PENDING;
    ServiceStatus.dwWaitHint =2000;
    SetServiceStatus (hStatus, &ServiceStatus);
    Sleep(1000);
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus (hStatus, &ServiceStatus);
    break;
  case SERVICE_CONTROL_SHUTDOWN :
    cont_running = 0;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCurrentState  = SERVICE_STOP_PENDING;
    ServiceStatus.dwWaitHint =2000;
    SetServiceStatus (hStatus, &ServiceStatus);
    Sleep(1000);
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus (hStatus, &ServiceStatus);
    break;
  }

  return 0;

}

void WINAPI ServiceMain(DWORD argc, LPSTR argv)
{
  int hServiceStatus;

  ServiceStatus.dwServiceType        = SERVICE_WIN32;
  ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
  ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  ServiceStatus.dwWin32ExitCode      = 0;
  ServiceStatus.dwServiceSpecificExitCode = 0;
  ServiceStatus.dwCheckPoint         = 0;
  ServiceStatus.dwWaitHint           = 0;

  hServiceStatus = RegisterServiceCtrlHandlerEx(MY_SVC_NAME, ServiceHandlerProc,0);
  /*
  if (hStatus == (SERVICE_STATUS_HANDLE)0) {
    return;
  }
  */

  Sleep(1000);

  ServiceStatus.dwCheckPoint=0;
  ServiceStatus.dwWaitHint=0;
  ServiceStatus.dwCurrentState=SERVICE_RUNNING;
  SetServiceStatus( hServiceStatus, &ServiceStatus);

  InitService();

  return;
}

void InitService()
{
  cont_running=1;
  do {
    system(THE_PROG);
    Sleep(SLEEP_TIME);
  } while (cont_running);
}

int main(int argc, char *argv[], char *envp[])
{
  SERVICE_TABLE_ENTRY ServiceStartTable[2];
  ServiceStartTable[0].lpServiceName = MY_SVC_NAME;
  ServiceStartTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
  ServiceStartTable[1].lpServiceName = NULL;
  ServiceStartTable[1].lpServiceProc = NULL;


  if (!StartServiceCtrlDispatcher(ServiceStartTable))
  {
    DWORD err = GetLastError();
    if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
      return 1;
  }

  return 0;
}

我引用了以下文件但没有成功
http://msdn.microsoft.com/en-us/library/ms809975.aspx
LUA 服务引用手册

最佳答案

问题似乎出在您的 SERVICE_STATUS_HANDLE hStatus 上。全局变量:在程序中没有赋值,但被多次使用。

此外,局部变量 int hServiceStatus完全没有意义。

解决方法:去掉hServiceStatus局部变量并替换每次使用 hServiceStatus使用正确的 hStatus多变的。

提示:也许你已经意识到这一点,但是你应该在收到控制命令时才设置 STOP_PENDING 状态,只有在你真正停止工作线程时才设置 STOPPED。

关于c - 如何正确使用 SetServiceStatus 告诉 Windows 我的服务正在停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8972416/

相关文章:

在 c 中将 lisp 字符串转换为树 - 程序崩溃但在 Debug模式下运行

c - CreateProcess是否不应该运行应用程序(nc.exe)?

nhibernate - NHibernate session 可以/应该保持打开多长时间?

windows - 使用 sc.exe 使用当前用户帐户创建 Windows 服务

c - "cannot collect variable"?

php - 在Visual Studio中为MongoDB编译PHP驱动程序

c - *C* 可接受的二维字符串输入?

c# - C#:运行和调试Windows服务

windows-services - MSDeploy安装windows服务?

c# - 如何通过 C# 暂停和继续 Windows 服务