#include<afx.h>void WINAPI ServiceMain();                                 //服务主函数
void WINAPI ServiceStrl(DWORD);                            //服务控制
void Init();                                               //初始化
BOOL IsInstalled();                                        //判断服务是否已安装
BOOL Install();                                            //安装服务
BOOL UnInstall();                                          //卸载服务
void Action();                                             //服务任务
char chServiceName[]="MyService";                          //服务名称
char chServiceDisplayName[]="MyService";                   //服务显示名称
char chServiceDescription[]="My service description.";     //服务描述
SERVICE_STATUS_HANDLE hServiceStatus;                      //服务句柄
SERVICE_STATUS ServiceStatus;                              //服务状态
DWORD dwThreadId;                                          //进程ID//程序主函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{    //初始化
    Init();    //获取进程ID
    dwThreadId=::GetCurrentThreadId();    //判断命令行参数,决定动作
    if(stricmp(lpCmdLine,"/install")==0)
        if(!IsInstalled())
            if(!Install())
                return 1;
    else if(stricmp(lpCmdLine,"/uninstall")==0)
        if(IsInstalled())
            if(!UnInstall())
                return 1;
    else
    {
        SERVICE_TABLE_ENTRY ServiceTableEntry[]=
        {
            {chServiceName,(LPSERVICE_MAIN_FUNCTION)ServiceMain},
            {NULL,NULL}
        };
        ::StartServiceCtrlDispatcher(ServiceTableEntry);
    }
    return 0;
}//初始化
void Init()
{
    hServiceStatus=NULL;
    ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
    ServiceStatus.dwCurrentState=SERVICE_STOPPED;
    ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
    ServiceStatus.dwWin32ExitCode=0;
    ServiceStatus.dwServiceSpecificExitCode=0;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWaitHint=0;
}//服务主函数
void WINAPI ServiceMain()
{
    ServiceStatus.dwCurrentState=SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;    //注册服务控制函数
    hServiceStatus=RegisterServiceCtrlHandler(chServiceName,ServiceStrl);
    if(!hServiceStatus)
    {
        MessageBox(NULL,"注册控制服务失败!","",MB_OK);
        return;
    }    //设置服务状态
    SetServiceStatus(hServiceStatus,&ServiceStatus);    ServiceStatus.dwWin32ExitCode=S_OK;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWaitHint=0;
    ServiceStatus.dwCurrentState=SERVICE_RUNNING;
    SetServiceStatus(hServiceStatus,&ServiceStatus);    //服务任务部分
    Action();    //退出服务
    ServiceStatus.dwCurrentState=SERVICE_STOPPED;
    SetServiceStatus(hServiceStatus,&ServiceStatus);
}//服务控制函数
void WINAPI ServiceStrl(DWORD dwMsg)
{
    switch(dwMsg)
    {
    case SERVICE_CONTROL_STOP:
        ServiceStatus.dwCurrentState=SERVICE_STOP_PENDING;
        SetServiceStatus(hServiceStatus,&ServiceStatus);
        PostThreadMessage(dwThreadId,WM_CLOSE,0,0);
        break;
    case SERVICE_CONTROL_PAUSE:
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    case SERVICE_CONTROL_PARAMCHANGE:
        break;
    default:
        break;
    }
}//安装服务
BOOL Install()
{
    //打开服务控制管理器
    SC_HANDLE hSCM=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if(!hSCM)
        return FALSE;    char chFilePathName[MAX_PATH];
    CString strFileName;
    char chSystemPath[MAX_PATH];
    char* chNewFileName;    //获取自身程序文件名和系统目录
    ::GetModuleFileName(NULL,chFilePathName,MAX_PATH);
    strFileName=chFilePathName;
    while(strFileName.Find("\\",0)!=-1)
        strFileName=strFileName.Right(strFileName.GetLength()-strFileName.Find("\\",0)-1);    //截取系统目录字符串,设置为system目录
    ::GetSystemDirectory(chSystemPath,MAX_PATH);
    for(int n=0;(unsigned int)n<strlen(chSystemPath);n++)
    {
        if(chSystemPath[n]=='3')
            chSystemPath[n]='\0';
    }
    chNewFileName=strcat(chSystemPath,"\\");
    chNewFileName=strcat(chSystemPath,strFileName);    //将自身复制到系统system目录下
    ::CopyFile(chFilePathName,chNewFileName,FALSE);    //创建服务
    SC_HANDLE hService=::CreateService(hSCM,chServiceName,chServiceDisplayName,
    SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
    chNewFileName,NULL,NULL,NULL,NULL,NULL);    //设置服务描述
    SERVICE_DESCRIPTION ServiceDescription;
    ServiceDescription.lpDescription=chServiceDescription;
    ::ChangeServiceConfig2(hService,SERVICE_CONFIG_DESCRIPTION,&ServiceDescription);    //释放句柄
    CloseServiceHandle(hSCM);    if(!hService)
        return FALSE;    //释放句柄
    CloseServiceHandle(hService);    MessageBox(NULL,"Install done!","",MB_OK);
    
    return TRUE;
}//判断服务是否已安装
BOOL IsInstalled()
{
    //打开服务控制管理器
    SC_HANDLE hSCM=::OpenSCManager(NULL,NULL,SERVICE_ALL_ACCESS);
    if(!hSCM)
        return FALSE;    //打开服务
    SC_HANDLE hService=::OpenService(hSCM,chServiceName,SERVICE_QUERY_CONFIG);
    if(!hService)
        return FALSE;    //释放句柄
    CloseServiceHandle(hSCM);
    CloseServiceHandle(hService);    return TRUE;
}//卸载服务
BOOL UnInstall()
{
    //打开服务控制管理器
    SC_HANDLE hSCM=::OpenSCManager(NULL,NULL,SERVICE_ALL_ACCESS);
    if(!hSCM)
        return FALSE;    //打开服务
    SC_HANDLE hService=::OpenService(hSCM,chServiceName,SERVICE_STOP|DELETE);
    if(!hService)
        return FALSE;    //停止服务
    SERVICE_STATUS ServiceStatus;
    ::ControlService(hService,SERVICE_CONTROL_STOP,&ServiceStatus);    //删除服务
    if(::DeleteService(hService))
        return FALSE;    //释放句柄
    CloseServiceHandle(hSCM);
    CloseServiceHandle(hService);    MessageBox(NULL,"UnInstall done!","",MB_OK);    return TRUE;
}//服务任务
void Action()
{
    MessageBox(NULL,"Service running!","NULL",MB_OK);
    Sleep(10000);
}

解决方案 »

  1.   

    1、服务程序中不能使用MessageBox来调试,尤其在Action()中,建议使用日志。
    2、Action除了弹出消息框,仅仅执行了10秒,之后服务进程就退出了,这不符合服务精神,应该是一个长期循环,只接收停止指令才退出。
      

  2.   

    服务程序中使用MessageBox要加上MB_SERVICE_NOTIFICATION标志。
      

  3.   

    谢谢各位,但是我现在要解决的问题是让服务能够正常地运行起来.
    服务在启动时,它提示"没有及时相应启动或控制请求"
    我觉得可能是服务启动后ServiceMain中需要及时设置服务的当前状态,但是我不知道要设置什么状态
    希望大家能够帮助我解决这个问题,谢谢,继续
      

  4.   

    你在调用Action函数之前执行的代码就是设置服务状态的。
      

  5.   

    BOOL InstallService()
    {

    char strDir[MAX_PATH ];
    HANDLE schSCManager,schService;

    memset(strDir,0,sizeof(TCHAR)*MAX_PATH);
    GetModuleFileName( NULL,strDir, MAX_PATH );
    schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);  

    if (schSCManager == NULL) 
    return false;

    LPCTSTR lpszBinaryPathName=strDir;

    schService = CreateService((struct SC_HANDLE__ *)schSCManager,"Service2","MB Service6",
    // service name to display 
    SERVICE_ALL_ACCESS,          // desired access 
    SERVICE_WIN32_OWN_PROCESS, // service type 
    SERVICE_AUTO_START,        // start type 
    SERVICE_ERROR_NORMAL,        // error control type 
    lpszBinaryPathName,          // service's binary 
    NULL,                        // no load ordering group 
    NULL,                        // no tag identifier 
    NULL,                        // no dependencies 
    NULL,                        // LocalSystem account 
    NULL);                       // no password 

    if (schService == NULL) 
    return false;  
    /* SERVICE_FAILURE_ACTIONS sdBuf={0}; sdBuf.lpRebootMsg=NULL;
    sdBuf.dwResetPeriod=3600*24;

    SC_ACTION action[3];

    action[0].Delay=60*1000;
    action[0].Type=SC_ACTION_RESTART;

    action[1].Delay=0;
    action[1].Type=SC_ACTION_NONE;
    action[2].Delay=0;
    action[2].Type=SC_ACTION_NONE;

    sdBuf.cActions=3;
    sdBuf.lpsaActions=action;
    sdBuf.lpCommand=NULL;

        if( !ChangeServiceConfig2(
            schService,                 
            SERVICE_CONFIG_FAILURE_ACTIONS, 
            &sdBuf) )                   
        {
            printf("%s ChangeServiceConfig2 failed\n",argv[1]);
            bSuccess = FALSE;
        }
        else
            printf("%s ChangeServiceConfig2 succeeded\n",argv[1]);

    */
    StartService(schService, 0, 0);
    CloseServiceHandle((struct SC_HANDLE__ *)schService); 

    return true;
    }
    这是程序安装时的代码
      

  6.   

    BOOL InstallService()
    {char strDir[MAX_PATH ];
    HANDLE schSCManager,schService;memset(strDir,0,sizeof(TCHAR)*MAX_PATH);
    GetModuleFileName( NULL,strDir, MAX_PATH );
    schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);   if (schSCManager == NULL)  
    return false;LPCTSTR lpszBinaryPathName=strDir;schService = CreateService((struct SC_HANDLE__ *)schSCManager,"Service2","MB Service6",
    // service name to display  
    SERVICE_ALL_ACCESS, // desired access  
    SERVICE_WIN32_OWN_PROCESS, // service type  
    SERVICE_AUTO_START, // start type  
    SERVICE_ERROR_NORMAL, // error control type  
    lpszBinaryPathName, // service's binary  
    NULL, // no load ordering group  
    NULL, // no tag identifier  
    NULL, // no dependencies  
    NULL, // LocalSystem account  
    NULL); // no password  if (schService == NULL)  
    return false;   
    /* SERVICE_FAILURE_ACTIONS sdBuf={0};sdBuf.lpRebootMsg=NULL;
    sdBuf.dwResetPeriod=3600*24;SC_ACTION action[3];action[0].Delay=60*1000;
    action[0].Type=SC_ACTION_RESTART;action[1].Delay=0;
    action[1].Type=SC_ACTION_NONE;
    action[2].Delay=0;
    action[2].Type=SC_ACTION_NONE;sdBuf.cActions=3;
    sdBuf.lpsaActions=action;
    sdBuf.lpCommand=NULL;  if( !ChangeServiceConfig2(
      schService,   
      SERVICE_CONFIG_FAILURE_ACTIONS,  
      &sdBuf) )   
      {
      printf("%s ChangeServiceConfig2 failed\n",argv[1]);
      bSuccess = FALSE;
      }
      else
      printf("%s ChangeServiceConfig2 succeeded\n",argv[1]);*/
    StartService(schService, 0, 0);
    CloseServiceHandle((struct SC_HANDLE__ *)schService);  return true;
    }
      

  7.   

    可能是没有调用到StartServiceCtrlDispatcher,我的就是这个问题!
      

  8.   

    也遇到了这个问题,也觉得是StartServiceCtrlDispatcher的问题,因为在使用ATL创建的服务就没有问题,能够正常运行,但是自己写的时候,直接就是使用OpenSCManager和CreateService来创建函数,并使用StartService来启动,所以觉得应该是这里的问题
    但是如果使用StartServiceCtrlDispatcher,就又牵涉到很多东西,不知道该怎么来弄用没有更简单的方法,不适用StartServiceCtrlDispatcher就能让服务顺利跑起来呢