2012年12月22日星期六

我眼中的北京特色

办证和发票
十多年前到中关村,当时有名的高科技街区,感受最深的就是一条街上都在问你要不要光盘、办证或者发票,难免感慨这就是所谓的高科技?现在技术发展了,兜售光盘的早已不见了踪影,但是办证和发票的生意依然红火。
今天,从中关村一路走到国家图书馆,仍然是一路的办证和发票,每个发问的人怀里都抱着一个幼小的孩子,我猜测这是由于一旦被抓后会从轻处理吧。现在虽然还不是最冷的时候,但是白天气温也在零下几度了。这些妇女就抱着孩子在地铁口散乱的站成一排,站在地铁建筑的背阴里,晒不到阳光,可怜那些挨冻的幼小的孩子们。她们不断地跟路过的人们重复着"办证、发票",极少有人作出反应。但是可以肯定的是她们的努力也不会白费,因为我也在路旁看到一个年轻人和一个妇女正在一堆证件中翻找属于他自己的那张,这应该是圆满成交的结果吧。比这些妇女数量更多的是撒得遍地都是的名片,各种不同的版式,不同的电话号码,相同的就是醒目的"办证"等字样。一路上到处都是,数地铁站和公交站处最多。也许是因为这一路上都是学校吧,学校门口也不少。路过的时候,我在想是这是由于有需求才出现的么,是什么样的条件或者环境创造了这样的需求呢?

小食摊
人流多的地方就有不断办证和发票的吆喝声,也同样就会有一堆堆的小食摊,这也是在其他地方很难见到的。而在北京的地铁出站口这样的小食摊就很多,在今天路过的这一路,以前去过的三元桥、天通苑等都让人印象深刻。这些地铁出站口最惨不忍睹的就是地上的各种垃圾,多数是拜这些办证名片和小食摊所赐。当看到地铁出站口满目疮痍的情景,我实在难以承受自己知道有文明这个词。北京的地铁站里是极少有商品经营的,而在地铁外就不一样了,各种小食摊满满当当。毫无疑问,这更是因为有强大的需求了,同样,什么样的条件或者环境创造了这样的需求呢?前几天看到电视上报道说人们吃早餐难,很多早餐不卫生。即使是这样的早餐都来不及坐下吃,只能带着边走边吃,或者在路边冷风里,或者在公交车或地铁里。这些在其他城市我很少看到的场景,在这里我看到了,我认为这是特色。

2012年7月9日星期一

Delphi多线程自定义消息丢失

我们的程序中有一个BUG,偶尔的时候程序没有按照正常的工作流程继续,所谓卡在了某一位置。
查看代码和日志后发现,工作流程的驱动是通过PostThreadMessage消息到主线程来进行的,当程序卡在某一位置时,消息是发送出去了,但没有到达消息处理函数中。所谓消息丢失了。
PostThreadMessage确实可能会使消息丢失,函数说明中明确提到了。所以更换为PostMessage,发消息到TApplication的Handle。但是消息丢失的情况更加频繁了。
看来利用TApplication来处理消息也不是好办法;只有把消息发送到主窗体,在主窗体中处理消息应该更加可靠。
虽然Delphi的帮助里对 TApplication的Handle说明是"Provides access to the window handle of the main form (window) of the application.",但是我们应该知道,这里的main form和Delphi程序里我们的主窗体是不一样的,尽管我们在Delphi的Project属性中设置时也是称作Main form。我们的设置的主窗体,在TApplication中是MainForm,我们的主窗体的Handle也只能用MainForm.Handle来获得。
最终解决,PostMessage消息到MainForm.Handle,然后在MainForm中进行处理,终于和谐了。

2012年7月1日星期日

不同浏览器在中文输入过程的细微差别

之前在使用QtWebkit的时候发现它对中文输出控制上跟其他浏览器有一点儿小的差别。现在就Chrome、Firefox、IE9简单对比一下对中文输入过程的处理。
打开一个包含文本输入框的网页,启用中文输入法,鼠标点击输入框,输入几个字母(输入法状态栏出现待选词,但还没有确认输入),在这时以三种方式失当前输入框失去焦点,一种是点击网页上空白区域,另一种是点击地址栏,最后一种是点击其他程序的窗口。
对于第一种方式,三种浏览器的行为是一样的,都是输入框失去焦点,输入法取消输入过程。
对于第二种方式,Firefox和IE9也都是取消输入过程,而Chrome却是把输入的字母当作键的内容填到了输入框,也就是说输中文输到一半的时候,失去焦点时会把刚才键入的字母当作输入内容。
对于第三种方式,Firefox和IE9都是保留输入法状态,当再切回时,仍然可以接着刚才未完成的输入过程继续按键;但是Chrome的行为却跟第二种方式时一致,把键入的字母当作输入内容填入了输入框。
可以看到Firefox和IE的行为是一致的,而Chrome有些不同。

2012年6月30日星期六

Git/Delphi/Bat自动化构建

最近重拾Delphi,开工的首件事情就是实现自动化构建。
沿用N年以前的方法,直接使用批处理脚本实现。对于一个小项目的自动化构建过程,无非就是取代码、编译、打包、测试等过程;对于大多数项目,恐怕连测试也没有,例如我现在做的这个。本来这些都是简单的东西,没啥需要多说的。只是这是第一次在Windows下使用Git,而且在编译时对Delphi工程的版本号进行了修改,所以简单记录一下。

1. 取代码并获取版本号
Windows下在命令行使用Git,最好是生成一个.sh脚本。所以取代码就用三行命令搞定。
ECHO git pull >> pull.sh
pull.sh
del pull.sh
获取版本号,在使用 Git 生成编译版本号这篇文章的基础上根据需要修改一下就好了。

2. 修改版本号
其实每次构建需要修改的就是版本号a.b.c.xxx中的xxx,让xxx与代码仓库中的revision对应起来,这样方便版本管理。
Delphi工程的版本信息是记录在资源文件中的,默认为与工程名同名的res文件中,是编译过的资源文件,不能直接修改。要想修改Delphi工程的版本号,可以在IDE中进行修改,这样就很不方便实现自动化构建过程中去修改版本号。记得以前在公司项目组的构建人员为了实现修改Delphi工程的版本号,用AutoIt3写了一个脚本,用Delphi的IDE打开工作,然后点击菜单、按钮等等,费尽了力气。
其实可以用另一种方式来解决,Delphi工程中可以包含多个资源文件,可以把版本信息放入一个单独的资源文件,使用文本格式保存,即rc文件,在编译前使用资源编译工具编译成res。具体为:
a. 创建一个version.rc,写入版本信息
b. 每次构建前使用脚本修改version.rc中的版本号,并编译version.rc生成version.res
c. 在Delphi工程中引入版本信息资源文件 {$R version.res version.rc}
d. 在Delphi工程属性中版本信息标签页中的包含版本信息选项去掉
使用以上步骤就可以方便的使用脚本修改版本号,完成自动化构建了。


2012年2月23日星期四

一次软件冲突的解决过程

这几天看完了调试九法,是本好书,只是道理该懂的人自然会懂,不懂的看了书也不会懂。
于是想起了几年前工作中遇到的一些问题,算是属于广义的调试吧。

有一次项目组收到技术支持人员的报告称,客户(一所学校)的机房安装过我们的软件E后,他们原来上课使用的教学软件K,就不能使用了。随后,我就收到了去现场解决软件冲突的任务。
到了学校的机房,我们先把所有计算机都启动,软件E和K都是开机就自动运行的,但是发现我们的软件E都正常启动了,而软件K却只有几台正常启动了,其他的都没有在运行。
接下来,我把一台软件K没有正常启动的计算机上的软件E卸载掉后,重新启动,发现软件K还是没有成功运行。
我们又卸载掉几台计算机上的软件E后,把所有计算机重新启动,发现还是装了软件E的计算机上软件E都正常运行了。但是,软件K还是只在几台计算机上启动成功,这些计算机有的装有软件E,有的并没有安装软件E。由此,我们判断,软件K是否能够运行,和安装软件E没有关系,也就是说软件E和K本身并不冲突。
但是,客户的机房确实是在安装完我们的软件E后才出现问题的,而且这期间没有安装过其他软件,计算机上也有还原保护系统在工作。
我再一次把所有计算机重新启动了一次,还是只有几台计算机上软件K在正常运行,而且每次重新启动后能正常运行软件K的计算机也不相同。正当百思不得其解的时候,我突然发现虽然软件K正常启动的计算机和前一次不同,但是它们的座位号却是一样的。我赶紧查看了所有能正常运行的软件K的座位号,发现它们的座位号都是不同的。我找到软件K保存座位号的注册表项,在软件K不能正常启动的计算机上去查看,发现注册表项中的值与已经运行的某个软件K的座位号是相同。到这时就很确定是软件K的座位号设置重复才导致了它不能正常启动的。于是,我们修改了一些重复的座位号后,重新启动计算机,这些计算机上的软件K也能够启动了。
这时,我几乎可以确定是安装我们的软件E的时候,机房管理员使用了系统同传的方式,就是在一台计算机上安装好后,然后把整个系统克隆到其他计算机上,导致软件K的座位号设置重复。机房管理员最终也确认了这一点儿。
最后,我们把所有计算机的软件K的座位号设置正确后收工。

其实以上过程还算不上有条理,所以效率不是很高,加上计算机上有还原卡,每次修改注册表项前都需要打开还原卡,修改后再设置还原卡。整个过程花了几个小时。
确定软件E和软件K本身并不冲突是一个分界点,此后就只在软件K的找原因了。
发现软件K的座位号设置也是比较偶然的,因为我们对软件K并不了解,它是其他公司开发的,之前我们并没有使用或看到过。虽然我们最后发现了座位号的问题,但是如果去询问软件K的技术支持人员可能他们会在第一时间就给出检查座位号设置的建议,因为他们更理解系统。