2008年9月20日星期六

9月20日广州OS Camp记录

Open Source Camp今天在广州鼎龙酒店举行。

和小罗过来参加,他说很想接触开源社区。

大会在M1大会议厅举行,人不少,但是很争气,都穿了黑社会制服--还是蛮不错的,不过背后就像广告广场。。

Peter介绍了OW2--是一个开源中间件,然后现在往BI方向发展。后来还介绍到了开源项目的托管(Codebase)--和sfgoogle code等不同的是,他们是有比较好的管理,而不是松散的,具体的好处貌似是适合比较稳定的软件版本或者是打算开源的企业应用。听得不太清楚,马上去了解下。

第一场我选了Conrad的Agile开发--他是来自香港thoughtworks的老外。thoughtworks在敏捷开发可是非常有名的。全英文的演讲。。幸亏勉强能听懂,问问题是不可能的了,英语退步了十万八千里。Conrad基本上是在回答别人的问题,都说的不错,问题有敏捷迭代中问题的分解,需求确定,和客户保持联系,测试驱动开发等等。

会上还碰到了Cyril,一起听了程勇的“使用开源软件构建高可用的集群”。讲的还不错,主要讲的是java方面的应用集群,以及数据库集群的一些方案。Java应用集群方面,介绍到了terracotta这个不需要特殊api的集群内通信(同步方案),他通过JVM底层API(来自JDK?)来获取JVM堆内信息,将指定的内存对象在集群内同步。这个点子不错,不需要应用程序知道这个过程,并且没有广播消息对网络的压力(通过单台服务器来进行同步)。另外程勇提到了同步策略方面,貌似说道不一定会在同一时刻把A内存同步到B和C机器,可能只是先同步到C。当时我就想问如果这个时候来了对C的请求,那么C上面给出的确是旧的数据,如何解决这个问题?另外,如果两个机器同时有新的业务更新的话,如何来做同步?可惜没有时间问了,时间都安排的很紧。如果不使用terracotta的话,有种让应用程序知道同步操作的方案,在同步server上面记录每个同步对象,以及是否dirty等信息,这样应该就能够实现准确的同步了,原理类似于多CPU内核共享缓存。后面还介绍了一种没有单点故障的mysql备份方案(mysql的主从方式是有单点故障的),就是使用SQL代理来对mysql进行操作,每个代理负责对两个mysql进行操作,上面会对故障处理进行封装。

最后是比较轻松的Why Python--刘鑫讲的。期间问到最喜欢的python功能是什么,我心理的答案是高级容器,不过我没有说,主要是怕在java或者ruby里面是不是都有?不太了解。省略1k字,嗯,python是好东西!

这次活动除了让我学到很多东西以外,也让我更加坚定地认为,由主办方来抽的抽奖方式中,我的运气往往不错,而由自己来抽的话,则很垃圾。。印象中我被抽中过的奖有《电脑爱好者》的全向modem,摄像头,unix-center的书等。这次居然让我包揽了活动的第一个和最后一个奖!第一个是四等奖的《硝烟中的Scrum和XP》,最后一个是唯一的一等奖--罗技V220无线鼠标。。。

^.^

2008年9月2日星期二

一些Windows编程小技巧

做了一段时间的Windows编程,可以说收获不小。

1. 让主进程进入调试器模式

上周做了一个小工具,封装了mp4box来进程媒体处理,发现了mp4box在处理损坏了的媒体文件的时候有会发生异常,但是它自己没有处理好,会导致异常被Windows捕捉到,而弹出了"Unhandled Exception"的窗口,导致程序阻塞,而我的程序刚好是用于自动化平台的。这个问题挺让人头疼的,对于同一个进程空间的异常,可以通过在FS:[0]来注册自己的结构化异常处理(SEH,在windows核心编程里面有)函数,所有为被捕捉的异常都会被交到这里来处理。

不同进程空间的没有了解到有什么好的处理办法(后来有人说可以通过系统的设置屏蔽掉默认的"Unhandled Exception"的警告)。当时有一种比较容易想到的做法,就是扫出当前的活动窗口,然后发送鼠标时间把其关闭,但是这个只能用超时来做,我不喜欢这种方式。

后来在msdn了解到有一种调试器模式创建进程,可以获得子进程在异常时候触发的各种调试信息,其中就包括地址访问出错,数组越界,除零错误等等,作为调试器,当然可以在这个时候终止掉被启动(被调试)的进程。

具体的可以参考微软关于调试器的资料:http://msdn.microsoft.com/en-us/library/ms679304(VS.85).aspx

2. 获取鼠标所在位置的窗口句柄

获取句柄可以使用WindowFromPoint(POINT)这个 API,获得句柄以后还有一系列的API可以用于获取窗口信息比如标题,尺寸,位置,父窗口等等。

实际使用过程中,发现对于某些窗口,不能直接获取,只能通过ClientWindowFromPoint(hwndFather, POINT)来在一个窗口区域获取子窗口,当然子窗口也要刚好覆盖了这个屏幕位置,这里的POINT坐标需要使用相对于父窗口的坐标--可以通过ScreenToClient来转换坐标。

另外发现一些窗口无法获取句柄,可能是根本就没有窗口句柄,有点奇怪。试过youku网站首页上面的那个flash窗口,是获取不了句柄的,我怀疑不是没有(因为他和ie应该是两个不同的窗口来的,不过也有可能是直接GDI画到上面),而是窗体比较高级,使用我找到的这些API没法获取。

3. 查找子进程的窗体位置

创建子进程以后,可以得到进程的Handle,不过貌似没有直接的办法获取窗体HWND,但是有别的办法,比如枚举窗口EnumWindows(),然后比较Handle或者窗体标题。这部分正准备做,还没有对比哪种实际上更好。

4. 查找网页上面的视频播放器位置

如果有鼠标,直接指过去就是了,如果没有人工操作,可以通过枚举IE窗口的子窗口,然后对比标题或者classID,如果没有的话,我现在用这种算法:

在要查找的区域,比如IE窗口,隔一定步长查找一下最深层的窗体HWND,对于1000*1000这样规模的屏幕,需要采样的点是10^4个,查找最深层窗体需要的层数可能是2-3层,可以限定一下,其实我只见过2层的。

已经采样得到的点,组成了一个Handle矩阵,每个handle组成的都是一个矩形,可能有嵌套。合法的视频窗口都是没有子窗口的,所以可以排除掉一些了,然后剩下的这些,可以取最大的一个当作是视频窗口了,在网页上面应该是正确的。如果遇到广告比视频大的情况,可能要辅以其他的判断方法了,比如查询其ClassID。

5. 在屏幕上面画画

用GDI函数。可以使用Rectangle()等函数,然后注册一个画笔到窗口对应的DC上面去来画矩形。我只用到了画矩形,很好用,选定视频以后把它圈出来。

6. 处理网页

我使用了ActiveX的IE控件,目前只是用于网页浏览,还有IDocHostUIHandler接口没有尝试,打算自己处理DOM。

没有使用Firefox的XPCOM接口,也作为未来尝试的一个计划。