• 编写windows服务程序


    2012-11-02 08:54 (分类:计算机程序)

          windows服务是一个运行在后台并实现勿需用户交互的任务的控制台程序,对于隐藏程序有很大帮助。

          用了几天时间概括了编写windows服务程序的轮廓,下面用伪码记录一下。


          

    //两个全局变量
    SERVICE_STATUS_HANDLE StatusHandle
    SERVICE_STATUS m_ServiceStatus


    void main()

    //一个程序可能包含若干个服务。每一个服务都必须列于专门的分派表中
    SERVICE_TABLE_ENTRY ServiceTable[2]; //结构类型的数组,
    ServiceTable[0].lpServiceName = "MemoryStatus"; //服务名
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; //服务主函数  
    ServiceTable[1].lpServiceName = NULL; //数组最后一个成员组默认都为NULL
    ServiceTable[1].lpServiceProc = NULL;    

    // 启动服务的控制分派机线程, 负责把程序主线程连接到服务控制管理程序SCM,通知服务控制程序//服务正在执行,并提供函数地址;为每一个传递到它的数组中的非空元素产生一个新的线程,每一//个进程开始执行由数组元素中的指明的ServiceMain函数;SCM启动一个服务程序之后,它会等待该/*程序的主线程去调StartServiceCtrlDispatcher。如果那个函数在两分钟内没有被调用,SCM将会认为这个服务有问题,并调用TerminateProcess去杀死这个进程。这就要求你的主线程要尽可能快的调用StartServiceCtrlDispatcher,开始启动服务解析*/

    StartServiceCtrlDispatcher(ServiceTable); 

    }


    ServiceMain 函数
    该函数是服务的入口点。它运行在一个单独的线程当中,这个线程是由控制分派器创建的。ServiceMain 应该尽可能早早为服务注册控制处理器

    void WINAPI ServiceMain()
    {
    //指定服务特征和其当前状态来初始化 ServiceStatus 结构
    m_ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
    //指示服务类型,创建 Win32 服务。赋值 SERVICE_WIN32;
    m_ServiceStatus.dwCurrentState=SERVICE_START_PENDING;
    //指定服务的当前状态。因为服务的初始化在这里没有完成,所以这里 状态为SERVICE_START_PENDING;
    m_ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN
    //这个域通知 SCM 服务接受哪个域,停止,关机停止

    m_ServiceStatus.dwWin32ExitCode=0; //是允许服务报告错误的关键
    m_ServiceStatus.dwServiceSpecificExitCode=0; //一般不关心,设为0

    m_ServiceStatus.dwCheckPoint=0; //是一个服务用来报告它当前的事件进展情况的
    m_ServiceStatus.dwWaitHint=0; //一般不关心,设为0

    //使用API函数RegisterServiceCtrlHandler()设置服务控制管理器SCM的服务控制处理函数
    //ServiceMain 应该尽可能早早为服务注册控制处理器(尽量1秒之内)。这要通过调用 //RegisterServiceCtrlHadler 函数来实现;调用RegisterServiceCtrlHandler函数去通知SCM //它的CtrlHandler回调函数的地址
    //SERVICE_STATUS_HANDLE StatusHandle是一个全局变量,当需要改变状态时 //SetServiceStatus()用它来标识一个服务。

    SERVICE_STATUS_HANDLE StatusHandle
    StatusHandle =RegisterServiceCtrlHadler("system",serviceCtrlHandler) //函数名称 //控制函数CtrlHandler函数地址

    //RegisterServiceCtrlHandler返回一个SERVICE_STATUS_HANDLE,这是一个32位的句柄。SCM用 //它来唯一确定这个服务。当这个服务需要把它当时的状态报告给SCM的时候,就必须把这个句柄传//给需要它的Win32函数


    //在RegisterServiceCtrlHandler函数返回后,ServiceMain线程要立即告诉SCM服务正在继续初始//化。具体的方法是通过调用SetServiceStatus函数传递SERVICE_STATUS数据结构。
    //通过调用 SetServiceStatus 函数,用 hStatus 向 SCM 报告服务的状态。

    //一旦服务被完全初始化,就应该重新初始化SERVICE_STATUS结构的成员,更改dwCurrentState //为SERVICE_RUNNING,然后把dwCheckPoint和dwWaitHint都改为0,将状态及时通告给服务控制管 //理器SCM,使用一个API函数SetServiceStatus()来实现这一目标

    m_ServiceStatus.dwCurrentState=SERVICE_START_RUNNING;
    m_ServiceStatus.dwCheckPoint=0;
    m_ServiceStatus.dwWaitHint=0;

    SetServiceStatus(StatusHandle,m_ServiceStatus )
    //服务的句柄 //SERVICE_STATUS结构的地址


    door();启动后门程序
    return;

    }




    void WINAPI ServiceCtrlHandler(DWORD dwControl) //服务控制函数
    {
    switch (dwControl)
    {

    case SERVICE_CONTROL_PAUSE:
    servicestatus.dwCurrentState = SERVICE_PAUSE_PENDING;
    // TODO: add code to set dwCheckPoint & dwWaitHint
    // This value need to try a lot to confirm 
    // ...
    SetServiceStatus(servicestatushandle, &servicestatus);
    // TODO: add code to pause the service
    // not called in this service
    // ...
    servicestatus.dwCurrentState = SERVICE_PAUSED;
    // TODO: add code to set dwCheckPoint & dwWaitHint to 0
    break;
    case SERVICE_CONTROL_CONTINUE:
    servicestatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
    // TODO: add code to set dwCheckPoint & dwWaitHint
    SetServiceStatus(servicestatushandle, &servicestatus);
    // TODO: add code to unpause the service
    // not called in this service
    // ...
    servicestatus.dwCurrentState = SERVICE_RUNNING;
    // TODO: add code to set dwCheckPoint & dwWaitHint to 0
    break;
    case SERVICE_CONTROL_STOP:
    servicestatus.dwCurrentState = SERVICE_STOP_PENDING;
    // TODO: add code to set dwCheckPoint & dwWaitHint
    SetServiceStatus(servicestatushandle, &servicestatus);
    // TODO: add code to stop the service
    Stop();
    servicestatus.dwCurrentState = SERVICE_STOPPED;
    // TODO: add code to set dwCheckPoint & dwWaitHint to 0
    break;
    case SERVICE_CONTROL_SHUTDOWN:
    // TODO: add code for system shutdown
    // as quick as possible
    break;
    case SERVICE_CONTROL_INTERROGATE:
    // TODO: add code to set the service status
    // ...
    servicestatus.dwCurrentState = SERVICE_RUNNING;
    break;
    }
    SetServiceStatus(servicestatushandle, &servicestatus);
    }





    //安装服务函数 


    //OpenSCManager函数是在创建一个服务对象(CreateService),并且把它加入到中要调用的API
    //打开服务管理数据库


    SC_HANDLE schService;
    SC_HANDLE schSCManager;
    schSCManager=OpenSCManager(
    NULL, //本地计算机
    NULL, //默认的数据库
    SC_MANAGER_ALL_ACCESS //要求所有的访问权
    );


    //创建进程


    CreateService(
    SC_HANDLE hSCManager,//服务控制管理程序维护的登记数据库的句柄,由系统函数 OpenSCManager 返回 
    LPCTSTR lpServiceName, //以NULL 结尾的服务名,用于创建登记数据库中的关键字
    LPCTSTR lpDisplayName, //以NULL 结尾的服务名,用于用户界面标识服务
    DWORD dwDesiredAccess, //指定服务返回类型
    DWORD dwServiceType, //指定服务类型
    DWORD dwStartType, //指定何时启动服务
    DWORD dwErrorControl, //指定服务启动失败的严重程度
    LPCTSTR lpBinaryPathName, //指定服务程序二进制文件的路径
    LPCTSTR lpLoadOrderGroup, //指定顺序装入的服务组名
    LPDWORD lpdwTagId, //忽略,NULL
    LPCTSTR lpDependencies, //指定启动该服务前必须先启动的服务或服务组
    LPCTSTR lpServiceStartName, //以NULL 结尾的字符串,指定服务帐号。如是NULL,则表示使用 LocalSystem 帐号 
    LPCTSTR lpPassword //以NULL 结尾的字符串,指定对应的口令。为NULL表示无口。 但使用LocalSystem时填NULL



    schService=CreateService(
    schSCManager, //服务管理数据库句柄
    TEXT(SZSERVICENAME), //服务名
    TEXT(SZAPPNAME), //用于显示服务的标识
    SERVICE_ALL_ACCESS, //响应所有的访问请求
    SERVICE_WIN32_OWN_PROCESS, //服务类型
    SERVICE_DEMAND_START, //启动类型
    SERVICE_ERROR_NORMAL, //错误控制类型
    szPath, //服务程序磁盘文件的路径
    NULL, //服务不属于任何组
    NULL, //没有tag标识符
    NULL, //启动服务所依赖的服务或服务组,这里仅仅是一个空字符串
    NULL, //LocalSystem 帐号
    NULL);


    删除服务时调用
    DeleteService;它只有一个参数(服务句柄)。我们可分四步完成
    1)、打开SCM句柄。
    2)、打开要删除的服务。
    3)、检查当前服务的状态确保服务已经停止。
    4)、删除服务并关闭所有打开的句柄。下面是一段删除服务的程序。

    SC_HANDLE Service,scm;
    SERVICE_STATUS status;
    BOOL success;
    
    scm = OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE); //打开SCM句柄。

    //打开要删除的服务
    Service = OpenService(scm,pszServiceName,SERVICE_ALL_ACCESS|DELETE);


    //检查当前服务的状态确保服务已经停止
    if (!Service){

    cout<<"OpenService ERROR:"<<GetLastError()<<endl;
    CloseServiceHandle(Service);
    CloseServiceHandle(scm);
    return false;
    }

    success = QueryServiceStatus(Service,&status);
    if (!success){

    cout<<"QueryServiceStatus ERROR:"<<GetLastError()<<endl;
    CloseServiceHandle(Service);
    CloseServiceHandle(scm);
    return false;
    }

    if (status.dwCurrentState!=SERVICE_STOPPED)
    {
    success = ControlService(Service,SERVICE_CONTROL_STOP,&status);
    if (!success){
    cout<<"ControlService ERROR:"<<GetLastError()<<endl;
    CloseServiceHandle(Service);
    CloseServiceHandle(scm);
    return false;
    }
    }
    //删除服务
    success = DeleteService(Service);

    if (!success){

    cout<<"DeleteService ERROR:"<<GetLastError()<<endl;

    CloseServiceHandle(Service);
    CloseServiceHandle(scm);
    return false;
    }
    bb//关闭所有打开的句柄
    CloseServiceHandle(Service);
    CloseServiceHandle(scm);
    return true;
  • 相关阅读:
    序列化二叉树
    把二叉树打印成多行
    按之字形打印数据
    对称的二叉树
    二叉树的下一个结点
    删除链表中重复的结点
    c语言中数组名a和&a详细介绍
    C语言输出格式
    回文素数
    求平均成绩
  • 原文地址:https://www.cnblogs.com/centos2017/p/7896670.html
Copyright © 2020-2023  润新知