打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
NT Service Control App
尚未学会走的时候,我就已经开始爬电线杆了。第一个成型的软件是一个NT服务程序的控制程序。为了写好它,白头发眼看就要钻出头皮了。现在写出来,发泄一下。

    我原先准备写个NT服务的^_^,不过线程类没搞懂,所以转而写一个控制服务的程序。在Delphi中,选择新建一个“Service Application”程序,然后编译一下,就是一个NT服务程序的骨架了。简单是简单,不过想让它丰满起来就难了,而且一些小问题掌握不到,它的控制程序可就不那么容易写了。
   
       一个NT服务的控制程序,意思就是说要用它来控制一个NT服务的安装、启动、停止、卸载这四个状态,它的过程是:
  1、先要打开系统的服务管理器(取得管理NT服务的权限);
    2、打开需要控制的NT服务(获得控制权);
    3、对该服务进行控制。

    做法是:
    一、使用 OpenSCManager打开本地默认的服务管理器。(用到这些API的时候,要先在USES中加入“winsvc”
    OpenSCManager的声明是:

        SC_HANDLE OpenSCManager(
  LPCTSTR lpMachineName,  // 计算机名。我做的只是控制本地的服务,所以这里用Nil。
  LPCTSTR lpDatabaseName, // 服务管理器名。打开默认的就用Nil,我不知道是不是还有别的
  DWORD dwDesiredAccess  // 你要获得什么样的权限(这个要查手册)
                         ); 

    先声明:
var
  schOpenSCManager : SC_HANDLE
        begin
  schOpenSCManager := OpenSCManager(Nil,Nil,SERVICE_ALL_ACCESS);
// 最后面那个参数是控制权限,意思是完全控制,当然还有其它的,查查书.
        end;

    这样,打开本地服务管理器的工作就完成了.

    二、检查我们要操作的服务是否存在,返回一个HANDLE来确认。这里要用到 OpenService(),它的原形是:
      SC_HANDLE OpenService(
  SC_HANDLE hSCManager,  //打开服务管理器后返回的HANDLE,也就是 schOpenSCManager
  LPCTSTR lpServiceName, //服务名称,这个很重要,不能写混了。看下文。
  DWORD dwDesiredAccess  //想获得什么权限。最好是SERVICE_ALL_ACCESS了。^_^
                          );


    三、要是OpenService()返回的值小于或等于0,我们就可以认为我们需要控制的服务没有安装。要是大于0,那就要用另一个API函数来确定它现在是什么状态。

         BOOL QueryServiceStatus(
  SC_HANDLE hService,// 这个写的是在上一步 OpenService 时返回的值,意思就是说指定特定的服务
  LPSERVICE_STATUS lpServiceStatus  // QueryServiceStatus() 返回的这个服务的状态
                               );

         我是这样写的:
         var
   sscStatus : TServiceStatus;
         begin
   QueryServiceStatus(schOpenService,sscStatus);  //此时,就可以得到服务当前的状态了

              Case sscStatus.dwcurretStatus of // 把当前状态写成Case语句,其实随便写,只要通过就行了。
                   SERVICE_STOPPED :
                           // 你的代码
                   SERVICE_RUNNING :
                           // 你的代码
                   SERVICE_PASUED :  
                           // 你的代码     //还有几种状态,查书看看吧。  
              end;
         end;

    四、确定是什么状态就好办了。如果schOpenService <= 0,那我们就需要安装。得用到 CreateService();在SDK文档中是这样定义的:

            SC_HANDLE CreateService(
  SC_HANDLE hSCManager,  //  上文提到的 schOpenSCManager

  LPCTSTR lpServiceName, //  重要:跟OpenService()中的lpServiceName的意思是一样的,都是你做服务程序时给服务起的名字。做服务的时候有一个是:DisplayName,这是显示在服务程序器中的名字;还有一个 Name :如果你建立服务程序时没改,那这里就得用默认的名字(默认的名字是service1);第三个是 ServiceStartName : 这个我没搞懂,也没用。

  LPCTSTR lpDisplayName, //就是上文说的显示在服务管理器中的名字
  DWORD dwDesiredAccess, //权限
  DWORD dwServiceType,  //类型,共有四个。具体意思我说不清楚。   SERVICE_WIN32_OWN_PROCESS是有自己进程的win32 服务。要跟你写服务程序时选择的一样。
  DWORD dwStartType,  // 是自动的啊,还是BOOT啊什么的,要跟你写服务程序时选择的一样。
  DWORD dwErrorControl, //出现错误怎么办?最好用:SERVICE_ERROR_IGNORE,忽略它。其它的可选项请看SDK的说明。
  LPCTSTR lpBinaryPathName,// 这个参数把我浑了至少三个小时。后来看大富翁,才知道Pchar(服务的完整路径加服务的名字)就可以了。
  LPCTSTR lpLoadOrderGroup,// 后面这五个我看了别人的介绍,但不是很清楚,都是用的NIL,
  LPDWORD lpdwTagId,
  LPCTSTR lpDependencies,
  LPCTSTR lpServiceStartName,
  LPCTSTR lpPassword
                      );

    用了这个CreatService()后,你需要控制的服务就加入服务管理器里了。打开服务管理器应该就可以看到了。如果上面的那个ServiceName跟你建立服务里的不一样的话,你也可以把服务安装到服务管理器里,但启动、停止、删除的控制都不行了,用 service /uninstall也删不掉的,只有到注册表里删了。

    五、安装好了之后,服务并没有启动,(如果你写服务的时候把 starttype选成Auto 或 boot的话,重启就自动启动了)。现在没有重启,要把它启动起来,要用到 StartService().
 
        BOOL StartService(
  SC_HANDLE hService,  //  从OpenService() 或 CreatService() 返回的值,我这里用的是 schOpenService,也就是OpenService()返回的。
  DWORD dwNumServiceArgs, //SDK中的说明是:[in] Number of strings in the lpServiceArgVectors array. If lpServiceArgVectors is NULL, this parameter can be zero.
  因为看的不是很懂,既然人家说可以zero的,我就写0了。
  LPCTSTR* lpServiceArgVectors //SDK当中关于这个参数的说明偶看不懂,说什么Argv[0]作为默认的服务名字什么的。我是按照人家的程序写的。
                       );

      我的写法是:
          var
    argv : Pchar;
          begin
            argv := Nil;
            StartService(schOpenService,0,argv);
          end;

      如果上面所说的你把Createservice()函数里的ServiceName的值写的和你写服务时的不一样,StartService 后你就会发现这个服务在服务管理器里的状态是“启动”,记住,不是“已启动”。当你关掉这个服务控制程序再运行时,会发现这个服务没安装(这是我遇到的问题。我是不是很笨?)


    六、删除服务 DeleteService() 函数

           BOOL DeleteService(
  SC_HANDLE hService  // OpenService() 或 CreateService() 返回的值.
                    );


          DeleteService(schOpenService);
          这一句就可以把已经安装的服务删除啦。


    七、停止服务。并没有StopService()这个函数。需要用 ControlService()这个函数来停止一个服务。

         BOOL ControlService(
  SC_HANDLE hService, //OpenService 或 CreateService() 的返回值
  DWORD dwControl,  //你向服务管理器发出的控制命令,这里是要停止这个服务,所以就是:SERVICE_CONTROL_STOP
  LPSERVICE_STATUS lpServiceStatus  // 这个服务当前的状态
                             );

    八、需要注意的除了ServiceName这个可能出错的问题外,还要注意你OpenService()服务里的权限问题,我们使用OpenService()时是为了下一步的操作,如果下一步的操作是要删除这个服务,那个在OpenService()时就要给出删除的权限,所以能给ALL_ACCESS时就尽量给了。
服务的状态还有几个后面是_PENDING的,意思应该是某个工作尚未完成吧。比如说停止了一个服务,但我们用QueryServiceStatus()得到的状态是:SERVICE_STOP_PENDING,所以我们就要让其它操作等待一下,直到停止动作完成。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Microsoft Service Manager
在WIN2000环境下编制Service
【原创】编写软件动态加载NT式驱动
WINDOWS后台服务程序编写
vc获取系统服务信息
Windows系统服务编程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服