Chinaunix首页 | 论坛 | 博客
  • 博客访问: 117662
  • 博文数量: 38
  • 博客积分: 2015
  • 博客等级: 大尉
  • 技术积分: 405
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-26 17:19
文章分类

全部博文(38)

文章存档

2011年(4)

2010年(34)

我的朋友

分类: WINDOWS

2010-11-13 15:08:58

  最近在写一个程序,用来实现每隔一段时间上传数据功能。为了使小程序一直跟随操作系统启动运行而运行,听建议说最好写成一个服务,设置开机启动服务就可以达到上述效果了。

在网上淘换了个VC程序代码,里面有详细的注释。代码如下:

#include
#include
#include
#include

char *SERVICE_NAME = "BeepService";    // 定义服务的名称
HANDLE terminateEvent = NULL;     // 定义用于控制ServiceMain执行的事件句柄
SERVICE_STATUS_HANDLE serviceStatusHandle;  // 定义与SCM通讯的服务状态句柄
int beepDelay = 20000;                // 定义间隔时间
BOOL pauseService = FALSE;      // 定义服务暂停的标志
BOOL runningService = FALSE;     // 定义服务运行的标志
HANDLE threadHandle = 0;      // 定义实现服务功能的线程句柄


VOID SendStatusToSCM (DWORD dwCurrentState,DWORD dwWin32ExitCode,
       DWORD dwServiceSpecificExitCode,DWORD dwCheckPoint,DWORD dwWaitHint)
{
  SERVICE_STATUS serviceStatus;
   serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;  //设置服务运行在其自身的进程中
  serviceStatus.dwCurrentState = dwCurrentState;    //设置服务的当前状态
   // 如果服务正在启动,则不接收和处理控制通知事件,否则接收所有的控制通知事件
  if (dwCurrentState == SERVICE_START_PENDING)
   serviceStatus.dwControlsAccepted = 0;
  else
   serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN;
   /* 如果服务具有特定的出错代码,则设置serviceStatus 的dwWin32ExitCode属性为
  ERROR_SERVICE_SPECIFIC_ERROR,并设置serviceStatus的dwServiceSpecificExitCode属性
  为特定出错代码,以显示特定的错误信息*/
  if (dwServiceSpecificExitCode == 0)
  {
   serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
   serviceStatus.dwServiceSpecificExitCode =0;
  }
  else
  {
   serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
   serviceStatus.dwServiceSpecificExitCode =dwServiceSpecificExitCode; //设置服务的特定出错代码
  }
   serviceStatus.dwCheckPoint = dwCheckPoint; //设置服务在启动、关闭和运行操作中反映操作进度的值
  serviceStatus.dwWaitHint = dwWaitHint;  //设置服务在执行启动、关闭和运行操作时将持续的时间值
   SetServiceStatus (serviceStatusHandle, &serviceStatus); //更新SCM中服务的状态信息
}


DWORD ServiceThread(LPDWORD param)
{  //使用Sleep函数将while控制流程挂起,然后在指定的毫秒数后自动唤醒
  while (1)
  {
      //服务功能程序接口位置

   Sleep(beepDelay); //将该线程挂起beepDelay中指定的毫秒数
  }
  return 0;
}


VOID Handler (DWORD controlCode)
{
 switch(controlCode)
 { // 处理停止服务事件
  case SERVICE_CONTROL_STOP:
   //通知SCM服务即将停止
   SendStatusToSCM(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 5000);
   runningService=FALSE;   //设置服务运行的标志
   SetEvent(terminateEvent); //设置终止事件句柄为活动状态,从而使ServiceMain函数得以继续执行
   return;
   // 处理暂停服务事件
  case SERVICE_CONTROL_PAUSE:
   if (runningService && !pauseService)
   {
    // 通知SCM服务即将暂停
    SendStatusToSCM( SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, 1000);
    pauseService = TRUE;     //设置服务暂停的标志
    SuspendThread(threadHandle);       //挂起新服务的线程
    SendStatusToSCM(SERVICE_PAUSED, NO_ERROR, 0, 0, 0);     //通知SCM服务暂停
   }
   break;
   // 处理继续服务事件
  case SERVICE_CONTROL_CONTINUE:
   if (runningService && pauseService)
   {
    // 通知SCM服务即将继续
    SendStatusToSCM( SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, 1000);
    pauseService=FALSE;     //设置服务暂停的标志
    ResumeThread(threadHandle);       //继续新服务的线程
    SendStatusToSCM(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);   //通知SCM服务继续
   }
   break;
   // 处理更新服务当前状态事件
  case SERVICE_CONTROL_INTERROGATE:
   break;
   // 处理关闭系统事件
  case SERVICE_CONTROL_SHUTDOWN:
   return;
  }
}

VOID ServiceMain(DWORD argc, LPTSTR *argv)
{  //调用RegisterServiceCtrlHandler函数获得服务状态句柄,并注册生成服务控制处理函数
  serviceStatusHandle =RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)Handler);
  //通知SCM服务即将启动,并设置启动操作的进度值为1,以及估计完成的时间值为5秒
  SendStatusToSCM(SERVICE_START_PENDING,NO_ERROR, 0, 1, 5000);
  // 创建terminateEvent事件句柄,以控制ServiceMain程序的执行
  terminateEvent = CreateEvent (0, TRUE, FALSE, 0);
  // 通知SCM服务即将启动,并设置启动操作的进度值为2,以及估计完成的时间值为1秒
  SendStatusToSCM(SERVICE_START_PENDING,NO_ERROR, 0, 2, 1000);
  // 获取启动参数,即蜂鸣的间隔时间值
  if (argc == 2)
  {
   int temp = atoi(argv[1]);
   //如果间隔值小于1秒,则使用缺省的间隔值
   if (temp < 1000)
    beepDelay = DEFAULT_BEEP_DELAY;
   else
    beepDelay = temp;
  }
   // 创建服务线程
  DWORD id;
   //创建服务所在的线程,ServiceThread是线程函数的起始地址,id用于获得线程的ID号
  threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ServiceThread,0, 0, &id);
  runningService = TRUE;   // 设置服务运行的标志
  // 通知SCM服务开始运行
  SendStatusToSCM(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
  // 监视terminateEvent 事件句柄的状态,如果处于活动状态,程序继续执行,否则阻止程序继续执行
  WaitForSingleObject (terminateEvent, INFINITE);
   // 如果terminateEvent 事件句柄处于活动状态,则关闭相关句柄,终止ServiceMain函数
  CloseHandle(terminateEvent);         //关闭terminateEvent事件句柄
    SendStatusToSCM(SERVICE_STOPPED, 0,0, 0, 0);   // 显示出错信息error,并通知SCM服务停止
     CloseHandle(threadHandle);          //关闭threadHandle线程句柄
}

VOID main(VOID)
{
 //填充SERVICE_TABLE_ENTRY结构,供StartServiceCtrlDispatcher函数调用
 SERVICE_TABLE_ENTRY serviceTable[] = {{ SERVICE_NAME,(LPSERVICE_MAIN_FUNCTION)
           ServiceMain},{ NULL, NULL }};
 BOOL success;
  //通过将新服务的ServiceMain函数的指针传递给SCM,实现新服务在SCM中的注册
 success = StartServiceCtrlDispatcher(serviceTable);
 if (!success) 
  ExitProcess(GetLastError());   //结束进程的执行
}
  

  将程序编译成Myservices.exe文件,把他放在c盘,在DOS命令符下输入 sc create  Myservices binpath= c:\Myservices.exe(Myservices 是服务的名字)。创建服务成功之后了,在运行里输入services.msc,打开服务,在里面找到Myservices 服务,启动它。OVER。删除服务命令:在DOS命令符下输入 sc delete 服务的名字。

 

阅读(1436) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~