Win2K 服务程序的源码(框架而已)

类别:VC语言 点击:0 评论:0 推荐:

 

  以下为 Win2000 下我所理解的服务程序的源码,可以创建一个服务,并可以随时启动,停止和移除该服务。使用VC6编译,下面是使用方法简介。

  需要安装 Service 的,打开 Dos 窗口,然后输入程序名字加上 -install 参数
 例如:

    #Simple_Service  -install

  如果需要删除 Service 的,在 Dos 窗口,输入程序名字加上 -remove 参数

    #Simple_Service  -Remove


  也可以使用工具 SC.exe 来删除服务,在 Dos 窗口输入  sc delete _Simple_Service_08 即可


  如果要启动或停止服务,请在计算机管理-> 服务那里启动 ,服务名称为 _Simple_Service_08

/////////////////////////////////////////////////////////////////////////////////////

  该服务程序会生成调试用的日志文件,需要包含 RunTimeLog.h 和 RunTimeLog.cpp
  这两个文件在这里 http://www.csdn.net/develop/Read_Article.asp?Id=17477


  下面的程序对刚刚入门的伙伴可能有用,"高手"们就省省墨水,免得我又被臭骂了(面对像这样的中国人,我不得不学乖一点)。

  以下是完整的源程序,文件名称是: WinMain.cpp,详细的说明待我组织过后再附上。

 

//********************************************************************************
//***************      FileName: WinMain.cpp      ********************************
//********************************************************************************
// 最小 Link 包含: msvcrt.lib kernel32.lib user32.lib Advapi32.lib Shell32.lib
#define WIN32_LEAN_AND_MEAN   // Say No to MFC !!
#define UNICODE

#include <windows.h>
 //#include <Winsvc.h>
 //#include <Shellapi.h>


#include "RunTimeLog.h"
RunTimeLog log;

LPSTR MsgErr=NULL;

 


//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Define for Service

#define ServiceName "_Simple_Service_08"
#define StrInstall TEXT("install")
#define StrRemove  TEXT("Remove")

void WINAPI service_ctrl(DWORD dwCtrlCode);
void WINAPI service_main(DWORD dwArgc,LPTSTR *lpszArgv);

void  WinMainCleanup(void);

SC_HANDLE                  schService=NULL, schSCManager=NULL;
SERVICE_STATUS             ssStatus;
SERVICE_STATUS_HANDLE      sshStatusHandle=NULL;
HANDLE                     hServerStopEvent = NULL;


//////////////////////////////////////////////////////////////////////////

 

 


// End of Define for Service


  char temp[1024]="Temp77 is Bad!";

 


////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
void  WinMainCleanup(void)
{
  if(MsgErr){ LocalFree(MsgErr); MsgErr = NULL; }
  if( schService ) CloseServiceHandle( schService );
  if(schSCManager) CloseServiceHandle(schSCManager);
  log.last(true);
  //log.showResult(1500);
  //log.write("after ShowResult!");
  return;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

// Name: WinMain()
// ------ ---------- ----------- ---------
int WINAPI WinMain( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow )
{

  log.nobuff = true;
  log.write(ServiceName" WinMain start");


  // 判断是否为 WinNT
  OSVERSIONINFO  osvi;
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if( GetVersionEx(&osvi) )
  {
    if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) log.write("WinNT 系统可用!");
    else { log.write("非 WinNT 系统中,清场后退出");  WinMainCleanup(); return 1; }
  }else
  {
    log.write("Failed to GetVersionEx.");
    FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                    GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
    log.write(MsgErr);
    WinMainCleanup(); return 1;
  }// End of  if( GetVersionEx(&osvi) )
 

 

  // 填充服务入口表
  SERVICE_TABLE_ENTRY  dispatchTable[] =
  {
    { TEXT(ServiceName), LPSERVICE_MAIN_FUNCTION(service_main) },
    { NULL, NULL }
  };


  // 取得命令行以观察
  LPSTR cmdline = GetCommandLineA();
  log.write("CommandLine by following."); log.write(cmdline); log.write("");


  // 取得当前目录以观察
  GetCurrentDirectoryA(1024,temp);
  log.write("CurrentDirectory by following."); log.write(temp); log.write("");

  // 取得模块的文件名以观察
  GetModuleFileNameA(NULL,temp,sizeof(temp));
  log.write("Current Module FileName by following."); log.write(temp); log.write("");

  for(int i1=lstrlenA(temp); i1>0; i1--) { if(temp[i1]=='\\') { temp[i1]=0;break; } }
  SetCurrentDirectoryA(temp);
  log.write("重新设置了当前目录的位置");

  // 重新取得当前目录以观察
  GetCurrentDirectoryA(1024,temp);
  log.write("CurrentDirectory by following."); log.write(temp); log.write("");


  // 分离出参数组以访问
  int NumArgsCount = NULL;
  LPWSTR * lpArgv = CommandLineToArgvW( GetCommandLineW(),  &NumArgsCount );
  log.numberwrite("NumArgsCount = ", (DWORD)NumArgsCount);

  int i=0;
  for(i=0;i<NumArgsCount;i++)
  {
    log.numberwrite("命令行参数 ",i);
    WideCharToMultiByte(CP_ACP, NULL, lpArgv[i],-1,temp,sizeof(temp),NULL,NULL);
    log.write(temp); log.write("");
  }

  // 判断参数的操作
  if(NumArgsCount>1) // 只有参数个数大于 1 的时候
  {
   if( (lpArgv[1][0]==(WORD)'/') || (lpArgv[1][0]==(WORD)'-') )
   {
     log.write("判断参数");
     if(!_wcsicmp(StrInstall, lpArgv[1]+1))
     {
       log.write("Install specify.");
       //CmdInstalService();

      if(!GetModuleFileNameA(NULL,temp,sizeof(temp))) { log.write("GetMouduleFileName failed.");  WinMainCleanup(); return 0; }

      // SC_HANDLE  schService=NULL, schSCManager=NULL;
      schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
     if(schSCManager)
     {
       log.write("OpenSCManager 成功");
       // 打开成功才创建
      schService =
       CreateServiceA( schSCManager, ServiceName, ServiceName"(Dsp)",
                       SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,
                       temp,NULL,NULL,NULL,NULL,NULL  );
       if(schService)
       {
         log.write("CreateService "ServiceName" 成功");
         CloseServiceHandle(schService); schService = NULL;
       }
       else
       {
         log.write("CreateService "ServiceName" failed.");

         FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                         GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
         log.write(MsgErr);
        
         WinMainCleanup(); return 0;
       }


       CloseServiceHandle(schSCManager); schSCManager = NULL;
     }
     else { log.write("OpenSCManager failed.");  WinMainCleanup(); return 0; }

     log.write("");
     log.write("完成了服务的安装");
     log.write("");

     }
     else if(!_wcsicmp(StrRemove,  lpArgv[1]+1))
     {
       log.write("Remove  specify.");
       //CmdRemoveService();

  // SC_HANDLE  schService=NULL, schSCManager=NULL;
  schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  if(schSCManager)
  {
    log.write("OpenSCManager 成功");
    // 打开成功才进行下一步
    schService = OpenServiceA( schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if(schService)
    {
      log.write("OpenService "ServiceName" 成功");

      QueryServiceStatus( schService, &ssStatus);
      if(ssStatus.dwCurrentState == SERVICE_STOPPED) log.write("Service already Stopped.");
      else
      {
        // try to Stop the Service
        log.write("try to Stop the Service");

        if( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ))
        {
          Sleep(50);
          while ( QueryServiceStatus( schService, &ssStatus))
          {
            if( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
            {
              Sleep(500);
              log.write("仍在停止 Service 中。。。");
            }
            else break;
          }//End of  while ( QueryServiceStatus( schService, &ssStatus))
        }

      }//End of  if(ssStatus.dwCurrentState == SERVICE_STOPPED) else

      // 如果已经停止了 Service ,那么就删除服务
      if(ssStatus.dwCurrentState == SERVICE_STOPPED )
      {
        Sleep(1000);
        if( DeleteService( schService) )  log.write("成功删除 "ServiceName" Service");
        else log.write("删除 "ServiceName" 失败");  log.write("");
      }
      else log.write("failed to Stop Service.");

     CloseServiceHandle(schService); schService = NULL;
    }
   else
   {
     log.write("OpenService "ServiceName" failed.");

     FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                     GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
     log.write(MsgErr);

     WinMainCleanup(); return 0;
   }
   CloseServiceHandle(schSCManager); schSCManager = NULL;
  }
   else { log.write("OpenSCManager failed.");  WinMainCleanup(); return 0; }


     }
   }
   WinMainCleanup();
   return 0;
  } // End of  if(NumArgsCount>1) // 只有参数个数大于 1 的时候

  log.write("");

  if(StartServiceCtrlDispatcher(dispatchTable)) log.write("StartServiceCtrlDispatcher Complete.");
  else
  {
    log.write("StartServiceCtrlDispatcher failed.");
    FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                    GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
    log.write(MsgErr);
  }

  
   WinMainCleanup();
   //ExitProcess(0);
   log.last(true);
   return NULL;

}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void WINAPI service_ctrl(DWORD dwCtrlCode)
{
// Handle the requested control code
  log.write("");
  log.write("Go into service_ctrl Function.");
  log.write("");
  int i2=0;
  switch(dwCtrlCode)
  {
    // Stop the Service
  case SERVICE_CONTROL_STOP:
    log.write("recive SERVICE_CONTROL_STOP");
    ssStatus.dwCheckPoint = ssStatus.dwCheckPoint++;
    ssStatus.dwWin32ExitCode = NO_ERROR;
    ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
    SetServiceStatus(sshStatusHandle,&ssStatus);

    SetEvent(hServerStopEvent);
    log.write("已经设置 Service 状态为 SERVICE_STOP_PENDING ,并将同步对象设置为激发状态.");

   for(i2=0; i2<12; i2++)
   {
     QueryServiceStatus( schService, &ssStatus);
     if( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )  Sleep(200);
     else break;
   }
   ResetEvent(hServerStopEvent);
   if(ssStatus.dwCurrentState == SERVICE_STOPPED )
   {
      log.write("The Service is now Stoped");
      ssStatus.dwCheckPoint = 0;
      ssStatus.dwWin32ExitCode = NO_ERROR;
      ssStatus.dwCurrentState = SERVICE_STOP;
      SetServiceStatus(sshStatusHandle,&ssStatus);
   } else  log.write("Stoped Service Failed.");

    return;
   break;
  case SERVICE_CONTROL_INTERROGATE:
    log.write("recive SERVICE_CONTROL_INTERROGATE");
   break;
  default:
    log.numberwrite("recive CtrlCode = ",dwCtrlCode);
    break;
  }

  //ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
  ssStatus.dwCheckPoint = ssStatus.dwCheckPoint++;
  ssStatus.dwWin32ExitCode = NO_ERROR;
  SetServiceStatus(sshStatusHandle,&ssStatus);


  return;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////


void service_mainCleanup(void)
{
  log.write("");
  log.write("service_mainCleanup!"); log.write("");

  if(hServerStopEvent){ CloseHandle(hServerStopEvent); hServerStopEvent = NULL; }

  ssStatus.dwWin32ExitCode = 0;
  ssStatus.dwCurrentState = SERVICE_STOPPED;
  ssStatus.dwWaitHint = 1000;
  if(SetServiceStatus(sshStatusHandle,&ssStatus))
  {
    log.write("SetServiceStatus to SERVICE_STOPPED 成功!");
  }
  else
  {
   log.write("SetServiceStatus to SERVICE_STOPPED 失败!");
   FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                   GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
   log.write(MsgErr);
  }
 
  //log.showResult(false);
  return;
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
void WINAPI service_main(DWORD dwArgc,LPTSTR *lpszArgv)
{

 // 注册我们的 Service 控制处理函数
 sshStatusHandle = RegisterServiceCtrlHandlerA(ServiceName,service_ctrl);
 if(!sshStatusHandle)
 {
   FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                   GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
   log.write(MsgErr);
   log.write("Failed to RegisterServiceCtrlHandler");
   service_mainCleanup();
 }

 log.write("");
 log.write("We now Running in service_main.");
 log.write("Success to RegisterServiceCtrlHandler");


 hServerStopEvent = CreateEvent(NULL,TRUE,false,NULL);
 if(hServerStopEvent) log.write("创建了同步对象");
 else  log.write("创建同步对象失败");

 

 // 以下是测试同步信号的代码
 DWORD dwWait = NULL;

 dwWait = WaitForSingleObject(hServerStopEvent,200);
 {
   if(dwWait==WAIT_TIMEOUT)  log.write("等待同步信号超时");
   if(dwWait==WAIT_OBJECT_0) log.write("同步对象被触发了");
 }


 // 继续报告现在 Service 启动的进度
  ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  ssStatus.dwServiceSpecificExitCode = 0;
  ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP ;//| SERVICE_ACCEPT_PAUSE_CONTINUE;
  ssStatus.dwWaitHint = 1000;

  // 设置以后放送
  ssStatus.dwCheckPoint = 0;
  ssStatus.dwWin32ExitCode = NO_ERROR;
  ssStatus.dwCurrentState = SERVICE_START_PENDING;

  if(SetServiceStatus(sshStatusHandle,&ssStatus))
  {
    log.write("SetServiceStatus 成功!");
  }
  else
  {
   log.write("SetServiceStatus 失败!");
   FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                   GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL );
   log.write(MsgErr);
  }


   Sleep(300);

  // 设置以后放送
  ssStatus.dwCheckPoint++;
  log.numberwrite("Progress = ",ssStatus.dwCheckPoint);
  ssStatus.dwWin32ExitCode = NO_ERROR;
  ssStatus.dwCurrentState = SERVICE_START_PENDING;

  SetServiceStatus(sshStatusHandle,&ssStatus);

 


  for(int i1=0; i1<6;i1++)
  {

    Sleep(300);
    // 设置以后放送
    //ssStatus.dwCheckPoint++;
    ssStatus.dwCheckPoint = ssStatus.dwCheckPoint + 20;
    log.numberwrite("Progress = ",ssStatus.dwCheckPoint);
    ssStatus.dwWin32ExitCode = NO_ERROR;
    ssStatus.dwCurrentState = SERVICE_START_PENDING;
    SetServiceStatus(sshStatusHandle,&ssStatus);

  }

   Sleep(200);

   // 设置以后放送
   ssStatus.dwCheckPoint = 0;
   ssStatus.dwWin32ExitCode = NO_ERROR;
   ssStatus.dwCurrentState = SERVICE_RUNNING;
   SetServiceStatus(sshStatusHandle,&ssStatus);
   log.write("SetServiceStatus to SERVICE_RUNNING !");

   Sleep(500);

 

// 放入代码运行服务

 

   
   while (true)
   {
      dwWait = WaitForSingleObject(hServerStopEvent,1);
      {
        //if(dwWait==WAIT_TIMEOUT)  log.write("等待同步信号超时");
        if(dwWait==WAIT_OBJECT_0) { log.write("同步对象被触发了"); ResetEvent(hServerStopEvent); break; }
      }
//////////////////////////////////////////////////////////////////////////

 

       log.write("Doing Something...");
       Sleep(100); // 假设要运行100毫秒的操作

 

 

 

 

 

//////////////////////////////////////////////////////////////////////////

   }// End of while (true)


service_mainCleanup();

  return;
}


 

本文地址:http://com.8s8s.com/it/it1525.htm