Main

September 08, 2013

BT 下载器下载的安装文件被杀毒软件卡住的问题

我们代理的游戏狂刃 客户端用 NSIS 制作成一个 exe 安装包,有 1G 左右。一开始,我们是购买又拍和七牛这种的云服务分发客户端。从用户的下载速度来看可以满意,但费用有点高。所以我们打算另外开发一个采用 BT 协议的下载器,这也是 MMO 客户端分发给客户的标配了。

rainfiel 同学在一个多月前主动领了这个任务,对 BT 的开源库考察一番后使用 libtorrent 开发这个下载器。

最近在测试的时候发现了一个问题,成功下载完安装包后,如果系统安装有 卡巴斯基 或 360 等杀毒软件,就会在调用 ShellExecute 第一次运行安装包时被卡住很久(长达几分钟)。用进程管理器查看,发现是杀毒软件一直在扫描刚下载的 exe 文件。

April 15, 2013

WM_CREATE 引起的 bug 一则

今天在维护一个 Windows 程序时,发现一个 bug ,记录一下。

这是一个简单的 Windows 程序,在注册给窗口的 WinProc 回调函数中处理了 WM_CREATEWM_PAINT WM_TIMER 等消息。

bug 的现象是,WM_CREATE 的流程没有走完就开始处理 WM_TIMER 等消息了。表现起来仿佛 WinProc 被重入了。

仔细排查后发现,不知道什么奇怪的原因,我的 Win7 系统在处理 WM_CREATE 消息时,默认捕获了异常。导致消息处理的流程没有走完,但进程却没有崩溃,窗口也被正确创建出来了。然后这个窗口可以继续接收 WM_TIMER 等消息。

February 13, 2009

ExtractAssociatedIcon 的一点问题

今天 卡牌对决 升级,没在 vista 下测试。晚上就有人报告 vista 下运行不了了。

netbug 同学在家里取了一份代码查看。据说错误是出在 ExtractAssociatedIcon 这个 api 的调用内部。是下面这样一行 api 调用:

hIncon = ExtractAssociatedIcon( inst, "loader.exe", &wIndex );

但是 msdn 上看不出所以然来。

之前,vista 下都是运行正常的。netbug 同学说,唯一的区别,以前是 vc6 编译的,而现在换成了 vc9 。

一般情况下,换编译器不会造成 api 调用失败呀?这是为什么呢?

December 26, 2006

使用 WSAAsyncSelect 的 Winsock 编程模型

前段时间思考了 Windows 下应用程序最合适的实现模型。写了这么一篇 blog 在 Windows 下使用 Timer 驱动游戏

我想,Windows 有 Windows 的哲学,Windows 平台下的应用程序,也有他的理念。关于 Windows 编程的书,我比较喜欢 Charles Petzold 的那本:《Windows 程序设计》(还有另一本是《WIndows 核心编程》,在第 5 版的 3.2 节中就提到 Windows 编程的难点在于“别调用我,我会调用您”以及“行动迅速”。

以前,我不十分理解 Windows 为什么把大量的任务放在消息循环中被动的调用,慢慢的我有点理解了。这就是 Windows 。

网络编程我一直是顺着 BSD socket 来学习和使用的,所以 Windows 下写 winsock 程序也一直没有改变习惯。这两天突然对这个做了下反思,按照 Windows 的理念来写 socket 程序应该是怎样的形式?查了下 msdn 后,发现了一个以前被我忽略掉的 api —— WSAAsyncSelect 。

以前粗读 mfc 的源码时,仿佛见过 CSocket 用这个来实现。当时没有太在意;也听不同的几个朋友跟我简单介绍过它,同样没有放在心上。直到今天,自己突然有兴趣了,才仔细研究了一下。

December 08, 2006

VC6 warning level 4 的问题

今天试着用 VC6 打开 warning 的第 4 级,把自己的项目编译了一遍。修正了自己程序中一些不规范的地方后,发现 windows 自己的 .h 文件里有个小问题 :(

问题出在 RPCASYNC.H 中,缺少一个 struct _RPC_ASYNC_STATE 的前置声明。这导致 include windows.h 后,会出现一条警告信息:

... \VC98\include\rpcasync.h(45) : warning C4115: '_RPC_ASYNC_STATE' : named type definition in parentheses

我目前的解决方案是在 include windows.h 前加上一句 struct _RPC_ASYNC_STATE;

December 06, 2006

在 Windows 下使用 Timer 驱动游戏

在 Windows 平台下写游戏,相比 console 等其它平台,最麻烦之事莫过于让游戏窗口于其它窗口良好的相处。

即使是全屏模式,其实也还是一个窗口。如果你不去跑窗口的消息循环,一个劲的刷新屏幕,我估计要被所有 Windows 用户骂死。

那么怎样让你的游戏程序做一个 Windows 下的良好公民呢?

December 04, 2006

LoadLibrary 的搜索次序

今天写程序的时候发现一个问题,我为 lua 写了一个叫作 console 的 C 扩展库,可老是加载失败。郁闷了好半天后终于找到问题,那就是 lua 解释器实际找到的是 windows/system32 下的一个同名 dll 文件。原来系统也有一个 console.dll 了。

记得从前没有这个问题的,上网查了下 msdn 终于发现其缘故了。原来 windows xp sp2 以后,动态链接库的缺省搜索次序被修改了。

Dynamic-Link Library Search Order

November 01, 2006

Windows 和 Unix 下动态链接库的区别

最近慢慢将开发环境转向了 freebsd ,渐渐的发现了许多东西跟 Windows 下不太一样。我指的是,跟我以前想当然的理解不太一样。比如,unix 下对动态链接库 so 的处理,和 Windows 下的 DLL 就不太相同。

之前,我对 Windows 下更为了解一些。早几年做 Windows 开发,老是为动态链接,静态链接这些问题纠缠不清;慢慢的才有了比较清晰的理解,现在基本上不会为这类问题困绕了。前段时间,碰到一些朋友写 lua 的扩展库(windows 版本)时遇到的几个 bug ,就是因为链接问题导致的。公司内部的一个项目,在服务器程序上也碰到了错误链接 lua 引起的 bug ,在内部 maillist 上争论了好久。当时,作为 windows 程序员,跟同事中的 unix 程序员争论看似相同的问题时,却老说不到一起去;今天才发现,原来是相互之间对动态链接库的理解不同导致的。

今天,写下本文,或许可以让以后跨平台开发的朋友少走点弯路。

August 14, 2006

Windows 下以非阻塞方式读取标准输入

最近遇到一个小问题,游戏的 client 在开发调试阶段需要接收控制台的输入指令。这个需求其实一直都有,只不过以前是自己写的控制台,那样反而好控制一些。使用 Windows 标准控制台也不是第一次,但是这个输入问题都没有好好的解决。这次又碰到这个问题,决定找个好点的解决方案。

读取标准输入的 C 函数,像 scanf , gets 这些都是阻塞方式的。一经调用,程序就塞在那里不动了。起初的想法是,既然控制台输入就是一个标准输入文件,那么把这个文件修改成非阻塞模式就可以了。google 了一下,似乎 windows 下并没有 fcntl 或是 ioctl 这样的东西可以修改 stdin 为非阻塞模式。或许有别的 windows API 吧,没精力去查。

比较丑陋的方法是用 _kbhit 检测键盘输入,这个方法不太符合我的审美观。想了一下,觉得还是另外开个线程清爽一点。反正是调试用,虽然从资源占用与效率角度看不太美妙,姑且也可以凑合了。

以下代码可以工作 :)

April 27, 2006

共享目录的重新登陆

我们办公室内部架设了 samba 服务器,用于存放共享文件。共享目录有两个密码,一个是只读的,一个是读写的。为了方便,一直是让 windows 记住密码。我负责维护一些文件,所以自然是读写密码。

前几天,公司内部网络调整,我们办公室被换了网段。自然,共享目录进不去了。时间太久,只能去翻笔记本找回当初的密码。一不小心,让 windows 记住了只读密码,居然找不到怎么注销了 :(

找了好久,才发现注销的位置在,控制面板——用户帐户——左上角有一个管理我的网络密码。删除掉密码后,依然发现问题没有解决,然后在 console 下输入 net use 发现连接还在,用 net use /delete 后问题解决了。

January 22, 2006

Windows 下最小的汉字点阵字摸

以前一直以为 Windows 下汉字点阵最小是 12px 的,依稀记得有朋友提过,其实还有更小的汉字字模。今天刻意想找,发现原来 MingLiu, PMingLiu 里提供了 11px 的汉字。因为字之间需要留白,实际字模是 10*10 大小的。

日文提供更小的汉字字模,MS UI Gothic 提供 10px 的点阵字体。

ps. 以前一直觉得 Opera 显示小字体的汉字怪怪的,有些网页看的不舒服。我用的英文版的 Opera 8.51 。今天找了下菜单,Tools - Prefences (Ctrl-F12) - Fonts 原来默认最小的字体(Mininum font size) 是 6px 的,改成 11px 后,在把默认中文字体设置成 MingLiu (International Fonts...) ,舒服多了 :)

January 03, 2006

安装字体

以前做游戏想用隶书,但是并非每台机器上都装有这个字体,所以有时候需要给用户提供一个。在自己软件的路径下放上字体文件,直接调用 CreateFont 这个 API 是不认的。

这种情况下可以使用 AddFontResource ,然后调用
PostMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0); 就可以了。
当不用这个字体时再调用 RemoveFontResource 卸掉。

October 27, 2005

Windows 对 DLL 文件的一些处理

Windows 的 DLL 文件是可以有别名的,它设置在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
中,用注册表编辑器,我们可以看到这个别名的列表。

比如有一条数据是 kernel32 / kernel32.dll 这条记录保证了再调用 LoadLibrary("kernel32.dll") 的时候,系统总是调用的 system32 下的 kernel32.dll 这个版本。而不会是当前目录下的 kernel32.dll (如果有的话)

October 26, 2005

Windows 下的进程间通讯及数据共享

Windows 下有很多方法实现进程间通讯,比如用 socket,管道(Pipe),信箱(Mailslot),等等。但最基本最直接的还是使用内存共享。其他方法最终还是会绕道这里。

可想而知,如果物理内存只有一份,让这份内存在不同的进程中,映射到各自的虚拟地址空间上,每个进程都可以读取同一份数据,是一种最高效的数据交换方法。下面我们就讨论如何实现它。

October 14, 2005

纤程

Widnows 是提供了用户级线程的,类似 coroutine 需要用户主动是切换。这在单线程程序中非常有用。线程调度模块只负责提供堆栈,环境的保存。不负责分配时间片等。

自己实现 coroutine 并不难,但能用操作系统提供的可以得到更多的便利。Windows 中把这种用户级线程叫做 Fiber,纤维的意思。比较通用的译名是纤程。