用Vc6写Windows 服务

来源:互联网 发布:网络食品监管总结报告 编辑:程序博客网 时间:2024/05/29 05:00

// ServiceTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <winsvc.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CWinApp theApp;
using namespace std;
//***********************************************************************************//
//变量声明
//***********************************************************************************//
//服务内部名
#define APPNAME "DBDataBackup"
//服务显示名
#define SZSERVICENAME _T("数据库定时清理服务")
//服务状态
SERVICE_STATUS ssStatus;
//服务句柄
SERVICE_STATUS_HANDLE sshStatusHandle;
//SC句柄
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR * lpServiceArgVectors;
//服务调试标志
BOOL bDebug=FALSE;
//互斥信号量
CRITICAL_SECTION errCritical;
//服务退出事件
HANDLE hSysExitEvent = NULL;
//***********************************************************************************//
//函数声明
//服务入口函数
void  WINAPI  Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);
//服务控制处理函数
void WINAPI Service_Ctrl(DWORD dwCtrlCode);
//标准错误输出函数
void StdErrorHandler(CString errorMessage);
//服务安装处理函数
void installService();
//服务卸载处理函数
void removeService();
//服务调试处理函数
void debugService();
//写服务日志
void AddToAppLog(CString errorMessage);
//获得系统时间
CString GetSystemTime();
//服务启动处理函数
void ServiceStart();
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint);
//服务停止处理函数
void ServiceStop();
//服务暂停处理函数
void ServicePause();
//服务继续处理函数
void ServiceContinue();

//***********************************************************************************//
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 //初始化信号量
 InitializeCriticalSection(&errCritical);
 //初始化MFC
 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
  cerr << _T("致命错误: MFC初始化失败") << endl;
  return -1;
 }
 else
 {
  //注册服务入口,服务名、服务入口函数
  //Windows执行服务入口在Service_Main
  SERVICE_TABLE_ENTRY dispatchTable[2]={
   {SZSERVICENAME,Service_Main},    
   { NULL,NULL}};
  //获得当前可执行文件目录和文件名
  char exeFullPath[MAX_PATH];
  GetModuleFileName(NULL,exeFullPath,MAX_PATH);
  for(int i=strlen(exeFullPath); i>=0; i--)
  {
   if(exeFullPath[i]=='//')
   {
    exeFullPath[i]=0;
    break;
   }
  }
  //设置当前进程的当前路径为服务的路径
  SetCurrentDirectory(exeFullPath); 
  //处理命令行参数
  if(argc>1&&*argv[1]=='-')
  {
   //参数为-install,安装服务
   if(_stricmp("install",argv[1]+1)==0)
   {
    //执行安装服务
    installService();
   }
   //参数为-remove,卸载服务
   else if(_stricmp("remove",argv[1]+1)==0)
   {
    //执行卸载服务
    removeService();
   }
   //参数为-debug,调试服务
   else if(_stricmp("debug",argv[1]+1)==0)
   {
    //置服务调试标志
    bDebug=TRUE;
    //执行调试服务
    debugService();
   }
   else
   {
    //参数格式不合法
    printf("输入 %s - install 来安装服务 /n",APPNAME);
    printf("输入 %s - remove 来卸载服务 /n",APPNAME);
    printf("输入 %s - debug 来调试服务 /n",APPNAME);
   }
   exit(0);
  }
  //如果未能和上面的如何参数匹配,则可能是服务控制管理程序来启动该程序。
  CString errmessage;
  printf("/n已调用StartServiceCtrlDispatcher./n");
  printf("这可能需要几秒钟,请等待./n");
  //立即调用StartServiceCtrlDispatcher函数。
  if(!StartServiceCtrlDispatcher(dispatchTable))
  {
   StdErrorHandler("调用StartServiceCtrlDispatcher失败.");
   AddToAppLog(errmessage);
  }
  else
  {
   StdErrorHandler("调用StartServiceCtrlDispatcher成功.");
   AddToAppLog(errmessage);
  }
 }
 return 0;
}

//******************************************************//
//服务入口函数
//******************************************************//
void  WINAPI  Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
{
 //注册服务控制处理函数,服务APPNAME,控制函数Service_Ctrl
 sshStatusHandle=RegisterServiceCtrlHandler(APPNAME,Service_Ctrl);
 //如果注册失败
 if(!sshStatusHandle)
 {
  CString err;
  err="服务注册失败";
  StdErrorHandler(err);
  goto cleanup;
  return;
 }
 //初始化 SERVICE_STATUS 结构中的成员
 ssStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
 ssStatus.dwServiceSpecificExitCode=0;
 //更新服务状态为正在启动SERVICE_START_PENDING
 if(!ReportStatusToSCMgr(
  SERVICE_START_PENDING, //服务状态,The service is starting.
  NO_ERROR,    //退出码         
  3000))     //等待时间
 {
  goto cleanup;   //更新服务状态失败则转向 cleanup
 }
 //服务启动主函数
 ServiceStart();
 return;

cleanup:
 //把服务状态更新为 SERVICE_STOPPED,并退出。
 if(sshStatusHandle)
 {
  ReportStatusToSCMgr(SERVICE_STOPPED,GetLastError(),0);
 }
}

 

//******************************************************//
//服务控制处理函数
//******************************************************//
void WINAPI Service_Ctrl(DWORD dwCtrlCode)
{
 //处理控制请求码
 switch(dwCtrlCode)
 {
 //先更新服务状态为 SERVICDE_STOP_PENDING,再停止服务。
 case SERVICE_CONTROL_STOP:
  {
   ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
   ServiceStop();     //由具体的服务程序实现
   ssStatus.dwCurrentState=SERVICE_STOPPED;
   break;
  }
 //暂停服务
 case SERVICE_CONTROL_PAUSE:
  {
   ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
   ServicePause();    //由具体的服务程序实现
   ssStatus.dwCurrentState=SERVICE_PAUSED;
   break;
  }
 //继续服务
 case SERVICE_CONTROL_CONTINUE:
  {
   ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
   ServiceContinue(); //由具体的服务程序实现
   ssStatus.dwCurrentState=SERVICE_RUNNING;
   break;
  }
 //更新服务状态
 case SERVICE_CONTROL_INTERROGATE:
  {
   break;
  }
 //无效控制码
 default:
  {
   break;
  }
    }
 //当前服务状态
 ReportStatusToSCMgr(ssStatus.dwCurrentState,NO_ERROR,0);
}

//******************************************************//
//服务安装处理函数
//******************************************************//
void installService()
{
 SC_HANDLE   schService;
    SC_HANDLE   schSCManager;
 TCHAR szPath[512];
 CString err;
 //得到程序磁盘文件的路径
 if(GetModuleFileName(NULL,szPath,512)==0)
 {
  err.Format("不能安装 %s - %s /n",TEXT(APPNAME),GetLastError());
  StdErrorHandler(err);
  return;
 }
 //打开服务管理数据库
 schSCManager=OpenSCManager(
  NULL,       //本地计算机
  NULL,       //默认的数据库
  SC_MANAGER_ALL_ACCESS   //要求所有的访问权
  );
 if(schSCManager)
 {
  //登记服务程序
  schService=CreateService(
   schSCManager,    //服务管理数据库句柄
   TEXT(APPNAME),    //服务名
   TEXT(SZSERVICENAME),  //用于显示服务的标识
   SERVICE_ALL_ACCESS,   //响应所有的访问请求
   SERVICE_WIN32_OWN_PROCESS, //服务类型
   SERVICE_AUTO_START,   //启动类型
   SERVICE_ERROR_NORMAL,  //错误控制类型
   szPath,      //服务程序磁盘文件的路径
   NULL,      //服务不属于任何组
   NULL,      //没有tag标识符
   NULL,      //启动服务所依赖的服务或服务组,这里仅仅是一个空字符串
   NULL,      //LocalSystem 帐号
   NULL);
  if(schService)
  {
   err.Format("%s 已安装.",TEXT(APPNAME));
   StdErrorHandler(err);
   CloseServiceHandle(schService);
  }
  else
  {
   err.Format("创建服务失败,服务可能已经安装");
   StdErrorHandler(err);
  }
  CloseServiceHandle(schSCManager);
 }
 else
 {
  err.Format("打开SCManager失败");
  StdErrorHandler(err);
 }
 CloseServiceHandle(schSCManager);
 return;
}

//******************************************************//
//服务卸载处理函数
//******************************************************//
void removeService()
{
 SC_HANDLE schService;
 SC_HANDLE schSCManager;
 CString err;
 //打开服务管理数据库
 schSCManager=OpenSCManager(
  NULL,    //本地计算机
  NULL,    //默认的数据库
  SC_MANAGER_ALL_ACCESS  //要求所有的访问权
  );
 if(schSCManager)
 {
  //获取服务程序句柄
  schService=OpenService(
   schSCManager,   //服务管理数据库句柄
   TEXT(APPNAME),   //服务名
   SERVICE_ALL_ACCESS  //响应所有的访问请求
   );
  if(schService)
  {
   //试图停止服务
   if(ControlService(
    schService,            //服务程序句柄
    SERVICE_CONTROL_STOP,  //停止服务请求码
    &ssStatus              //接收最后的服务状态信息
    ))
   {
    err.Format("停止 %s 中",TEXT(APPNAME));
    StdErrorHandler(err);
    Sleep(1000);
    //等待服务停止
    while(QueryServiceStatus(schService,&ssStatus))
    {
     if(SERVICE_STOP_PENDING==ssStatus.dwCurrentState)
     {
      cout<<".";
      Sleep(1000);
     }
     else
     {
      break;
     }
    }
    if(SERVICE_STOPPED==ssStatus.dwCurrentState)
    {
     err.Format("/n %s 已被停止. /n",TEXT(APPNAME));
     StdErrorHandler(err);
    }
    else
    {
     err.Format("/n %s 试图停止失败. /n",TEXT(APPNAME));
     StdErrorHandler(err);
    }
   }
   //删除已安装的服务程序安装
   if(DeleteService(schService))
   {
    err.Format("%s 已经被卸载. /n",TEXT(APPNAME));
    StdErrorHandler(err);
   }
   else
   {
    err.Format("删除服务失败");
    StdErrorHandler(err);
   }
   CloseServiceHandle(schService);
  }
  else
  {
   err.Format("连接服务失败,不存在此服务");
   StdErrorHandler(err);
  }
  CloseServiceHandle(schSCManager);
 }
 else
 {
  err.Format("打开SCManager失败");
  StdErrorHandler(err);
 }
}

 

//******************************************************//
//服务启动处理函数
//******************************************************//
void ServiceStart()
{
 //默认监测周期是3分钟
 int nWaitTime=3000;
 // 向SCM报告目前的状态
 ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 20000);

 if(!(hSysExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL))){
  StdErrorHandler("服务退出事件创建失败");
  return;
 }
 // 向SCM报告当前进度,运行状态
 ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0);
 StdErrorHandler("服务已启动");
 long int times=20;
 while(times)
 { 
  times--;
  cout<<times<<",";
  // 等待停止标志
  if(WaitForSingleObject(hSysExitEvent, nWaitTime) == WAIT_OBJECT_0)
  {   
   // 通知SCM服务正在结束
   ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 10000);
   StdErrorHandler("数据库定时清理服务正在终止...");
   return;
  }
  Beep(1000,200);
  Sleep(nWaitTime);
 }
}
//******************************************************//
//服务停止处理函数
//******************************************************//
void ServiceStop()
{
 SetEvent(hSysExitEvent);
}

//******************************************************//
//服务暂停处理函数
//******************************************************//
void ServicePause()
{}

//******************************************************//
//服务继续处理函数
//******************************************************//
void ServiceContinue()
{}


//******************************************************//
//服务日志记录处理函数
//******************************************************//
void AddToAppLog(CString errorMessage)
{
 
}
//******************************************************//
//服务调试处理函数
//******************************************************//
void debugService()
{
 ServiceStart();
}

//******************************************************//
//返回当前系统时间
//******************************************************//
CString GetSystemTime()
{
 SYSTEMTIME systemTime;
 CString timeString;
 GetLocalTime(&systemTime);
 timeString.Format("%04d年%02d月%02d日 %02d:%02d:%02d",
  systemTime.wYear, systemTime.wMonth, systemTime.wDay,
  systemTime.wHour, systemTime.wMinute, systemTime.wSecond,
  systemTime.wMilliseconds);
 return timeString;
}

/*******************************************************
名称:ReportStatusToSCMgr
参数:
 dwCurrentState:当前状态
 dwWin32ExitCode:win32退出码
 dwWaitHint: 该状态可能持续的时间
返回值:BOOL
功能:向Service Control Manager报告状态
*******************************************************/
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
       DWORD dwWin32ExitCode,
       DWORD dwWaitHint)
{
 static DWORD dwCheckPoint = 1;
 BOOL fResult = TRUE;
 
 if(!bDebug) {
  // 如果在初始化状态,不接受任何命令
  if(dwCurrentState == SERVICE_START_PENDING)
   ssStatus.dwControlsAccepted = 0;
  else
   ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

  ssStatus.dwCurrentState = dwCurrentState;
  ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  ssStatus.dwWaitHint = dwWin32ExitCode;

  // 如果状态为正在运行或已经停止,则checkpoit为0
  if((dwCurrentState == SERVICE_RUNNING) ||
   (dwCurrentState == SERVICE_STOPPED)){ 
   ssStatus.dwCheckPoint = 0;
   dwCheckPoint = 1;
  }
  else 
   ssStatus.dwCheckPoint = dwCheckPoint++;

  // 向服务管理器报告当前状态
  if(!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) {
//   StdErrorHandler(COMMANDHANDLER, "向SCM报告状态失败", SERVICEFLAG);
  }
 }
 return fResult;
}

//******************************************************//
//报告系统错误
//******************************************************//
void StdErrorHandler(CString errorMessage)
{
 EnterCriticalSection(&errCritical);
 AddToAppLog(errorMessage);
 printf("%s:%s/n",GetSystemTime(),errorMessage);
 LeaveCriticalSection(&errCritical);
}

原创粉丝点击