首先你的console程序要能响应service control.
要知道怎么做,请用ATL模版生成一个什么也不做的Service看看他是如何工作的.提示:
RegisterServer说明了如何向service manager注册;

解决方案 »

  1.   

    Windows NT 下Service 的 编 程 
    ---- Windows NT Server 提 供 多 种 功 能 强 大 的 服 务(Service), 例 如FTP,WWW 或 远 程 登 录 服 务, 另 外 常 用 的 数 据 库 服 务 器 也 是 以Service 的 形 式 存 在 于NT Server 上 的, 如Sybase SQL Server For NT。Service 一 般 在NT 启 动 时 自 动 启 动, 在NT 关 机 时 停 止。 但 是 有 时 用 户 可 能 想 手 工 启 动﹑ 暂 停﹑ 停 止 某 项Service, 这 就 需 要 在 控 制 面 板 中 进 行 配 置, 对 于 不 太 熟 悉NT 的 用 户 来 说 比 较 困 难; 对 于 软 件 开 发 人 员, 有 时 需 要 在 软 件 中 访 问 和 操 作 某 项Service, 甚 至 可 能 需 要 开 发 新Service 的 提 供 给 用 户 使 用。 上 面 两 种 情 况 都 可 以 通 过 对Service 的 编 程 来 解 决。 对Service 的 编 程 涉 及 到NT 的 内 核, 比 较 复 杂 且 相 关 资 料 较 少, 给 软 件 开 发 人 员 带 来 很 多 困 难, 笔 者 通 过 对Windows NT 的API 的 分 析 找 到 了 相 应 的 编 程 方 法, 再 此 介 绍 给 大 家。 
    ---- 在Windows NT 下, 各 种Service 都 存 在service control manager database 中, 因 此 我 们 可 以 通 过 对service control manager database 进 行 操 作 来 实 现 对Service 的 编 程。 下 面 介 绍 常 用 的 函 数: 
      1:SC_HANDLE  OpenSCManager
          (LPCTSTR  lpszMachineName,
          LPCTSTR  lpszDatabaseName,
          DWORD    fdwDesiredAccess); 
    ---- OpenSCManager 函 数 打 开 指 定 计 算 机 上 的service control manager database 。 其 中 参 数lpszMachineName 指 定 计 算 机 名, 若 为 空 则 指 定 为 本 机。 参 数lpszDatabaseName 指 定 要 打 开 的service control manager database, 默 认 为 空。 
    ---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一 
            SC_MANAGER_ALL_ACCESS       //所有权限
            SC_MANAGER_CONNECT     
          //允许连接service control manager
            SC_MANAGER_CREATE_SERVICE  
          //允许创建服务对象并把它加入
          service control manager database 
            SC_MANAGER_ENUMERATE_SERVICE
        //允许枚举service control manager database中的服务
            SC_MANAGER_LOCK     
          //允许锁住service control manager database
            SC_MANAGER_QUERY_LOCK_STATUS 
        //允许获取service control manager database的封锁信息
    ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 一 个 指 向service control manager database 的 句 柄, 失 败 则 返 回NULL。 
      2:SC_HANDLE OpenService
          (SC_HANDLE  schSCManager,
          LPCTSTR    lpszServiceName,
          DWORD      fdwDesiredAccess);
    ---- OpenService 函 数 打 开 指 定 的Service。 
    ---- 其 中 参 数schSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回。 
    ---- 参 数lpszServiceName 要 打 开 的 服 务 的 名 字, 注 意 大 小 写。 
    ---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一 
    SERVICE_ALL_ACCESS         
        //所有权限
        SERVICE_CHANGE_CONFIG     
        //允许更改服务的配置
        SERVICE_ENUMERATE_DEPENDENTS 
        //允许获取依赖于该服务的其他服务
        SERVICE_INTERROGATE 
        //允许立即获取服务状态
        SERVICE_PAUSE_CONTINUE 
        //允许暂停和唤醒服务
        SERVICE_QUERY_CONFIG
      //允许获取服务配置
        SERVICE_QUERY_STATU  
        //允许通过访问service control manager获取服务状态
        SERVICE_START 
        //允许启动服务
        SERVICE_STOP   
        //允许停止服务
        SERVICE_USER_DEFINE_CONTROL
    //允许用户指定特殊的服务控制码---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 指 向 某 项 服 务 的 句 柄, 失 败 则 返 回NULL。 
    3:BOOL QueryServiceStatus
          (SC_HANDLE        schService,
              LPSERVICE_STATUS  lpssServiceStatus);
    ---- QueryServiceStatus函数返回指定服务的当前状态。 
    ---- 其中参数schService是指向某项服务的句柄,由OpenService函数返回,且必须SERVICE_QUERY_STATUS的权限。 
    ---- 参数lpssServiceStatus中存放返回的服务状态信息,结构如下 
    typedef struct _SERVICE_STATUS {  
    DWORD dwServiceType;
                  //服务类型
    DWORD dwCurrentState;
                  //当前状态
    DWORD dwControlsAccepted;
              //服务可接受的控制码
    DWORD dwWin32ExitCode; 
              //Win32出错代码
    DWORD dwServiceSpecificExitCode;
        //服务出错代码
    DWORD dwCheckPoint;
        //用于跟踪服务长时间操作
    DWORD dwWaitHint;
        //服务某一操作的最大允许时间,以毫秒为单位
    } SERVICE_STATUS, *LPSERVICE_STATUS; 
    ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 
        4:BOOL StartService(SC_HANDLE  schService,
                      DWORD      dwNumServiceArgs,
                      LPCTSTR      *lpszServiceArgs);
    ---- StartService 函 数 启 动 指 定 的 服 务。 
    ---- 其 中 参 数schService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回, 且 必 须 有SERVICE_START 的 权 限。 
    ---- dwNumServiceArgs 为 启 动 服 务 所 需 的 参 数 的 个 数。 
    ---- lpszServiceArgs 为 启 动 服 务 所 需 的 参 数。 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 
        5:BOOL ControlService(
            SC_HANDLE        hService,
            DWORD            dwControl,
            LPSERVICE_STATUS  lpServiceStatus);
    ---- ControlService 函 数 向Win32 service 发 送 控 制 码。 
    ---- 其 中 参 数hService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回。 
    ---- 参 数dwControl 为 控 制 码, 常 用 的 有 
    SERVICE_CONTROL_STOP 
                //停止服务
    SERVICE_CONTROL_PAUSE
              //暂停服务
    SERVICE_CONTROL_CONTINUE
            //唤醒暂停的服务 
    SERVICE_CONTROL_INTERROGATE
      //刷新某服务的状态
    ---- 参 数lpServiceStatus 指 向SERVICE_STATUS 结 构, 用 于 存 放 该 服 务 最 新 的 状 态 信 息。 
    ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 
    6:BOOL EnumServicesStatus
              (SC_HANDLE  hSCManager,
                  DWORD      dwServiceType,
                  DWORD      dwServiceState,
                  LPENUM_SERVICE_STATUS  lpServices, 
                  DWORD      cbBufSize,
                  LPDWORD    pcbBytesNeeded,
                  LPDWORD    lpServicesReturned,
                  LPDWORD    lpResumeHandle);
    ---- EnumServicesStatus 函 数 用 于 枚 举NT 下 存 在 的Service。 
    ---- 其 中 参 数hSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回, 且 必 须 有SC_MANAGER_ENUMERATE_SERVICE 的 权 限。 
    ---- 参 数dwServiceType 指 定 按 服 务 的 类 型 枚 举。 
    ---- 参 数dwServiceState 指 定 按 服 务 的 状 态 枚 举。 
    ---- 参 数lpServices 指 向ENUM_SERVICE_STATUS 结 构, 用 于 存 放 返 回 的 服 务 的 名 字 和 状 态 信 息。 
    ---- 参 数cbBufSize 返 回 参 数lpServices 的 长 度, 以 字 节 为 单 位。 
    ---- 参 数pcbBytesNeeded 返 回 获 取 剩 余 的Service 所 需 字 节 的 个 数。 
    ---- 参 数lpServicesReturned 返 回 服 务 的 个 数。 
    ---- 参 数lpResumeHandle, 当 第 一 次 调 用 时 该 参 数 为0, 当 该 函 数 再 次 被 调 用 以 获 取 另 外 的 信 息 时, 该 参 数 表 示 下 一 个 被 读 的Service。 
    ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 
    ---- 值 得 注 意 的 是 通 常 情 况 下 该 函 数 返 回 的 结 果 为FALSE, 我 们 可 以 调 用GetLastError() 来 获 取 进 一 步 信 息。 因 为 一 台 机 器 上 有 多 种 服 务 存 在, 所 以GetLastError() 应 为ERROR_MORE_DATA, 此 时 应 再 次 调 用EnumServicesStatus 函 数 以 获 取 正 确 的Service 列 表。 
      

  2.   

    偷懒了,这是一个服务程序的例子。#include "windows.h"
    #include "winsvc.h"void WINAPI ServiceMain(DWORD dwArgc,LPTSTR * lpszArgv);
    void WINAPI Handler(DWORD Opcode);SERVICE_STATUS_HANDLE ssh;
    SERVICE_STATUS ss;int main(int argc,char * argv[])
    {
        SERVICE_TABLE_ENTRY ste[2];
        ste[0].lpServiceName="ServiceDemo";
        ste[0].lpServiceProc=ServiceMain;
        ste[1].lpServiceName=NULL;
        ste[1].lpServiceProc=NULL;
        StartServiceCtrlDispatcher(ste);
        return 0;
    }void WINAPI ServiceMain(DWORD dwArgc,LPTSTR * lpszArgv)
    {
        ssh=RegisterServiceCtrlHandler("ServiceDemo",Handler);
        
        ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS¦SERVICE_INTERACTIVE_PROCESS;
        ss.dwCurrentState=SERVICE_START_PENDING;
        ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
        ss.dwWin32ExitCode=NO_ERROR;
        ss.dwCheckPoint=0;
        ss.dwWaitHint=0;
        
        SetServiceStatus(ssh,&ss);
        //put your coed here
        ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS¦SERVICE_INTERACTIVE_PROCESS;
        ss.dwCurrentState=SERVICE_RUNNING;
        ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
        ss.dwWin32ExitCode=NO_ERROR;
        ss.dwCheckPoint=0;
        ss.dwWaitHint=0;
        
        SetServiceStatus(ssh,&ss);
        //put your coed here
    }void WINAPI Handler(DWORD Opcode)
    {
        switch(Opcode)
        {
        case SERVICE_CONTROL_STOP:
            //put your code here
            ss.dwCurrentState=SERVICE_STOPPED;
            ss.dwWin32ExitCode=0;
            ss.dwCheckPoint=0;
            ss.dwWaitHint=0;
            
            SetServiceStatus(ssh,&ss);
            break;
        case SERVICE_CONTROL_INTERROGATE:
            SetServiceStatus(ssh,&ss);
            break;
        }
    }
    以上是一个完整的服务程序。 服务程序还需要一个安装程序,将它安装(即OnCreate()函数的处理),启动等操作,下面分别是,服务安装一次后就可以了,就已经添加到注册表中,在控制面板的服务中可以看到的,不需要每次都安装的:OnStart() 
    {
        scm=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if(scm!=NULL)
        {
            scv=::OpenService(scm,"ServiceDemo",SERVICE_ALL_ACCESS);
            if (scv!=NULL)
            {
                ::StartService(scv,0,NULL);
                ::CloseServiceHandle(scv);
            }
            ::CloseServiceHandle(scm);
        }
    }OnCreate() 
    {
        scm=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if (scm!=NULL)
        {
            scv=::CreateService(scm,
            "ServiceDemo",
            "ServiceDemo",
            SERVICE_ALL_ACCESS,
            SERVICE_WIN32_OWN_PROCESS¦SERVICE_INTERACTIVE_PROCESS,
            SERVICE_AUTO_START,
            SERVICE_ERROR_IGNORE,
            "E:\\VC_DEMO\\ServDemo\\Debug\\ServDemo.exe",
            NULL,NULL,NULL,NULL,NULL);
            if (scv!=NULL)
            {
                ::CloseServiceHandle(scv);
            }
            else
            {
                ::CloseServiceHandle(scm);
            }
        }
    }
    OnDelete() 
    {
        scm=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if (scm!=NULL)
        {
            scv=::OpenService(scm,"ServiceDemo",SERVICE_ALL_ACCESS);
            if (scv!=NULL)
            {
                ::QueryServiceStatus(scv,&ss);
                if (ss.dwCurrentState==SERVICE_RUNNING)
                {
                    ::ControlService(scv,SERVICE_CONTROL_STOP,&ss);
                }
                ::DeleteService(scv);
                ::CloseServiceHandle(scv);
            }
            ::CloseServiceHandle(scm);
        }
    }OnStop() 
    {
        scm=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if(scm!=NULL)
        {
            scv=::OpenService(scm,"ServiceDemo",SERVICE_STOP¦SERVICE_QUERY_STATUS);
            if (scv!=NULL)
            {
                ::QueryServiceStatus(scv,&ss);
                if (ss.dwCurrentState==SERVICE_RUNNING)
                {
                    ::ControlService(scv,SERVICE_CONTROL_STOP,&ss);
                }
                ::CloseServiceHandle(scv);
            }
            ::CloseServiceHandle(scm);
        }
    }