写一个Windows上的守护进程(3)句柄的管理
写一个Windows上的守护进程(3)句柄的管理
在Windows中编程,跟HANDLE打交道是家常便饭。为了防止忘记CloseHandle,我都是使用do-while-false手法:
void f()
{
HANDLE h = NULL; do
{
} while (false); if (h)
{
CloseHandle(h);
h = NULL;
}
}
HANDLE一多,就得写好几段长得一样的清理代码,比较麻烦。仔细一想,这个其实很容易写一个关闭器——在出作用域时自动关闭:
class closer : public boost::noncopyable
{
public:
closer(HANDLE h)
: h_(h)
{ } ~closer()
{
if (h_)
{
CloseHandle(h_);
h_ = NULL;
}
} private:
HANDLE h_;
};
创建或打开一个句柄后,将其关闭动作委托给closer。
这是我在写这篇文章的时候想到的,写代码的时候我用的是另一个办法:scoped_handle。这是从boost里边那些运用RAII手法的类上学到得,比如scoped_ptr,scoped_array,名字也是学过来的:
template<HANDLE invalid_value = NULL>
class scoped_handle : public boost::noncopyable
{
public:
scoped_handle()
: h_(invalid_value)
{
} scoped_handle(const HANDLE &h)
: h_(h)
{
} ~scoped_handle()
{
destory();
} //you should ensure not self-assignment
void reset(const HANDLE &h)
{
destory();
h_ = h;
} void destory()
{
if (h_ != invalid_value)
{
//CloseHandle will set last error code
//so we should recover it
//someone may use reset(CreateFile(...))
last_error_recover r; CloseHandle(h_);
h_ = invalid_value;
}
} bool valid() const
{
return h_ != invalid_value;
} HANDLE& get_ref()
{
return h_;
} HANDLE* get_ptr()
{
return &h_;
} private:
HANDLE h_;
};
有一个模板参数invalid_value,这是句柄的无效值,我现在见到的有两种:NULL,INVALID_HANDLE_VALUE。
用法举例:
scoped_handle<> hProcess(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
if (!hProcess.valid())
{
ErrorLogLastErr("OpenProcess[%lu] fail", pid);
}
else
{
s = query(hProcess.get_ref(), native_name);
}
scoped_handle<> hToken;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken.get_ptr()))
{
//...
}
scoped_handle<> m_exit_event;
m_exit_event.reset(CreateEvent(NULL, TRUE, FALSE, NULL));
if (!m_exit_event.valid())
{
//...
}
我现在为自己找了一个不使用closer的理由:我不喜欢让别人帮助我做力所能及的事。closer就像是某人new了一个对象,然后把指针给了另一个人,让他去“擦屁股”,然而自己“擦屁股”不过是举手之劳。不过,这个理由不强劲,closer的便利性远远大于对“擦屁股”的厌恶。
这里有一个todo:我希望能定制Close动作,就是Close动作作为一个模板参数,这样一来,我就可以把HANDLE也提到模板参数的位置上,这个东西的适用范围就更广了,但是我不知道如何把Close动作提到模板参数的位置上。
想必眼尖的同学看到了上面的代码里有个last_error_recover,这是一个很简单的类,注释已经说明了它的用途,下面是实现:
class last_error_recover : public boost::noncopyable
{
public:
last_error_recover()
: code_(GetLastError())
{
} last_error_recover(const DWORD code)
: code_(code)
{
} ~last_error_recover()
{
SetLastError(code_);
} private:
const DWORD code_;
};
源码:https://git.oschina.net/mkdym/DaemonSvc.git (主)&& https://github.com/mkdym/DaemonSvc.git (提升逼格用的)。
2015年10月31日星期六
写一个Windows上的守护进程(3)句柄的管理的更多相关文章
- 写一个Windows上的守护进程(8)获取进程路径
写一个Windows上的守护进程(8)获取进程路径 要想守护某个进程,就先得知道这个进程在不在.我们假设要守护的进程只会存在一个实例(这也是绝大部分情形). 我是遍历系统上的所有进程,然后判断他们的路 ...
- 写一个Windows上的守护进程(7)捕获异常并生成dump
写一个Windows上的守护进程(7)捕获异常并生成dump 谁都不能保证自己的代码不出bug.一旦出了bug,最好是崩溃掉,这样很快就能被发现,若是不崩溃,只是业务处理错了,就麻烦了,可能很长时间之 ...
- 写一个Windows上的守护进程(6)Windows服务
写一个Windows上的守护进程(6)Windows服务 守护进程因为要开机启动,还要高权限,所以我就把它做成Windows服务了. 关于Windows服务的官方文档,大家可以看https://msd ...
- 写一个Windows上的守护进程(5)文件系统重定向
写一个Windows上的守护进程(5)文件系统重定向 在Windows上经常操作文件或注册表的同学可能知道,有"文件系统/注册表重定向"这么一回事.大致来说就是32位程序在64位的 ...
- 写一个Windows上的守护进程(4)日志其余
写一个Windows上的守护进程(4)日志其余 这次把和日志相关的其他东西一并说了. 一.vaformat C++日志接口通常有两种形式:流输入形式,printf形式. 我采用printf形式,因为流 ...
- 写一个Windows上的守护进程(2)单例
写一个Windows上的守护进程(2)单例 上一篇的日志类的实现里有个这: class Singleton<CLoggerImpl> 看名字便知其意--单例.这是一个单例模板类. 一个进程 ...
- 写一个Windows上的守护进程(1)开篇
写一个Windows上的守护进程(1)开篇 最近由于工作需要,要写一个守护进程,主要就是要在被守护进程挂了的时候再把它启起来.说起来这个功能是比较简单的,但是我前一阵子写了好多现在回头看起来比较糟糕的 ...
- 写一个Windows服务
做了两个和Windows服务有关的项目了,最开始的时候没做过,不懂,现在明白了许多.需要注意的是,如果不想登录什么的,最后在添加安装程序的那里选择那个字长的右键属性,把启动方式改为local syst ...
- 写一个限制上传文件大小和格式的jQuery插件
在客户端上传文件,通常需要限制文件的尺寸和格式,最常用的做法是使用某款插件,一些成熟的插件的确界面好看,且功能强大,但美中不足的是:有时候会碰到浏览器兼容问题.本篇就来写一个"原生态&quo ...
随机推荐
- Tomcat unable to start
在学习springMvc时,导入springfreemarker 的jar包,写好web.xml,config.xml 后. 部署到tomcat,异常如下: 八月 27, 2016 5:44:41 下 ...
- OpenGL ES 2.0 卷绕和背面剪裁
基本知识 背面剪裁是指渲染管线在对构成立体物体的三角形图元进行绘制时,仅当摄像机观察点位于三角形正面的情况下才绘制三角形. OpenGL ES中规定若三角形中的3个顶点的卷绕顺序是逆时针则摄像机观察其 ...
- OpenGL ES 2.0 曲面物体的构建
球体构建的基本原理构建曲面物体最重要的就是找到将曲面恰当拆分成三角形的策略. 最基本的策略是首先按照一定的规则将物体按行和列两个方向进行拆分,这时就可以得到很多的小四边形.然后再将每个小四边形拆分成两 ...
- bootstrap-paginator 分页控件的使用
首先对js和css的引用 <link rel="stylesheet" href="reference/bootstrap/css/bootstrap.min.cs ...
- Mysql学习(慕课学习笔记5)约束
约束类型: 1.NOT NULL (非空约束) 2.PRIMARY KEY(主键约束) 每张数据表只能存在一个主键 主键保证记录的唯一性 主键自动为NOT NULL (Auto_increment ...
- java-web-dom4j解析XML-递归方式
<?xml version="1.0" encoding="UTF-8"?><书架> <书 出版日期="2013-10 ...
- SpringSource Tools Suite 字体偏小问题
参照了Eclipse小技巧收录http://liuzidong.iteye.com/blog/1320094 发现没有找到相应文件,只有搜索了,一个一个地找,总算找到了,修改方法还是一样,只是路径,文 ...
- 为Mac自带的Apache配置PHP和虚拟机
操作系统:os x 10.11.2 1.启动apache 打开终端(terminal),输入命令:sudo apachectl -k start ; 在浏览器地址栏中输入:http://localho ...
- cocos2d-js 入门一 ([isNaN()和isFinite(),字符和Number之间的转化)
isNaN() : 用于检查其参数是否是非数字值.// 提示:是非数字哦.(not a number)document.write(isNaN(0) ) //返回falsedocument.writ ...
- strace基本操作
可以发现很多真正在系统层面发生的调用,以及很细微的返回错误信息,用于调试工作.(比如,软件出错,或是性能变慢...) strace -p 32000 -o strace.txt 基本上完整的用法是这样 ...