用C++编制Win32 Service (一)

来源:互联网 发布:有linux版本的qq吗 编辑:程序博客网 时间:2024/06/05 19:11
  .Net和Delphi都对Service进行了很好的封装,但是用C++编写Service还是一件很烦琐的事情。先写一些辅助类吧:

// 管理Service的句柄
class ServiceHandle {
public:
    ServiceHandle(SC_HANDLE h) : h_(h) {
        if (!h_)
            throw SysError();
    }
    ~ServiceHandle() { ::CloseServiceHandle(h_); }
    operator SC_HANDLE () { return h_; }
private:
    SC_HANDLE    h_;
    ServiceHandle(const ServiceHandle &); // disallowed
    ServiceHandle & operator = (const ServiceHandle &); // disallowed
};

// 分析命令行参数
class CmdLine {
public:
    CmdLine(void) {
        args_ = ::CommandLineToArgvW(GetCommandLineW(), &argCount_);
        if (!args_)
            throw SysError();
        current_ = 1;
    }
    ~CmdLine(void) {
        if (args_)
            ::GlobalFree(reinterpret_cast<HGLOBAL>(args_));
    }
    const wchar_t * getNext(void) {
        if (current_ < argCount_)
            return args_[current_++];
        else
            return 0;
    }
    int getCount(void) const { return argCount_-1; }
private:
    wchar_t        **    args_;
    int                argCount_;
    int                current_;
};

  凡是需要释放资源的东西(如上面的GlobalFree、CloseServiceHandle等等),我都喜欢写个简单的类来封装,让析构函数来防止我忘记做这事儿。:)
  单个的EXE允许含有多个服务(尽管不太常见),所以需要有一个东西来维护多个服务的列表,同时也便于根据服务名来查找相应的服务类(因为Windows的回调函数只能是静态函数而不能是类方法)。我用ServiceBase这个基类来表示一个服务,使用时从这个基类继承(Template模式),同时用ServiceApplication这个类来管理维护ServiceBase列表,进行服务的安装卸载工作,以及对命令行的解析,第一反应ServiceApplication应该是个Singleton,但似乎也可以仅让“服务列表”这个成员变量成为一个静态成员(用 std::map<std::wstring, ServiceBase *> > 作为变量类型似乎是个不错的选择)。
  值得一记的是具有13个参数的API: CreateService(),有几个地方需要记录一笔:
  • 如果指定SERVICE_INTERACTIVE_PROCESS标志,则该服务被允许与桌面交互,不过据其他资料记载,这里面含有不安全因素(主要是权限的不当提升),而且在Windows将来的版本中,也许会取消这个特性。
  • 默认启动服务的帐号是LocalSystem,这个帐号具有相当高的权限,而在XP及以后版本中,推荐用LocalService或NetworkService这两个权限相对较低的帐号来启动服务。
  • 通常我们创建的服务会有一些描述信息(Description),这个可以在成功安装服务后,用ChangeServiceConfig2()这个API来实现。