« 再谈"平等" | 返回首页 | 冰与火之歌果然是个好游戏 »

ExtractAssociatedIcon 的一点问题

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

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

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

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

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

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

我上 google 搜到了 msdn 里关于 ExtractAssociatedIcon 的文档 ,( google ExtractAssociatedIcon site:msdnmicrosoft.com)。

HICON ExtractAssociatedIcon(
HINSTANCE hInst, LPTSTR lpIconPath, LPWORD lpiIcon );

我注意到,这第二个参数类型是 LPTSTR 而不是 LPCTSTR 。

建议 netbug 同学改成:

char filename[]="loader.exe";

hIncon = ExtractAssociatedIcon( inst, filename, &wIndex );

居然就对了。-_-

之所以换了编译器就出问题,可能是因为不同的 linker 的策略不一样。或许 vc9 把 "loader.exe" 放到了一个只读段里去了,因为 vista 的 api 实现不太一样,导致去写一个只读页。(也有可能是 vista 的 PE Loader 的区别,不想深究了)


之所以这次我能在半分钟内反应过来,是因为以前碰到过类似的 Windows 版本之间平台差异问题。

GetGlyphOutline 就有这个问题。如果说 ExtractAssociatedIcon 的 msdn 文档还隐晦了指出了问题,GetGlyphOutline 就能肯定是 bug 了。

GetGlyphOutline 的最后一个参数类型是 const MAT2 *lpmat2 ,写明了是 const 。但是如果你定义一个 static const MAT2 ,然后把指针传进去的话,某个平台的 windows 下,进程会崩溃在这个 api 调用里。(可能是 Windows 98 ,因为这是很多年前开发大话 client 时遇到的了)


btw, netbug 同学在家里想 checkout 办公室内部的 svn ,而我们并没有提供外部 vpn 登陆的途径。而我还在办公室。有什么简单的办法呢?我发现 ssh 的 tunnel 功能可以安全的解决这个问题。

我们找了台外部大家都可以 ssh 登陆的机器,然后我先 ssh 上去,做一个 remote tunnel ,把我可以看见的办公室内部的 svn tunnel 到那台机器的本地。然后 netbug 同学再 ssh 过去,做一个 local tunnel 把管道对接回他家里的 PC 就 OK 了。 :D

这个方法值得推广。


2009 年 2 月 14 日补充:

今天 netbug 同学重新读了 msdn 文档,发现文档中提到了,第二个参数是有可能被改写的。不过文档中没有正确标明类型是 [in,out] ,而是标注成 [in] 。

不过奇怪的是,既然这个指针有可能接收返回串,但却并没有指定最大长度,是否会有栈溢出的安全隐患?

谨慎起见,需要把 filename 定义成:

char filename[MAXPATH]="xxxx";

(严格说,应该是用 TCHAR)

Comments

我用vc,但只是cl.exe,而不是visual c++ ide。

子民信息网www.3p3d.com看到贵老兄的Blog在此留个脚印。思绪来得快去得也快,偶尔会在这里停留

Vista下Createprocess执行报异常。

CreateProcess也会有这个问题,它的第二个参数也必须是一个可写的内存指针,否则会崩溃。"Window核心编程"上有介绍

vc 跟 gcc 一样只是编译器而已,有的同事喜欢用就用了。没有用 IDE 。

btw, 我写的那几篇东西也是以 vc 编译器来举例的呀?

不过我个人和大部分同事都还是在用 gcc 。这个是自由选择的。


看来你们也在用VC吗,看了你的几篇文章,我还以为你们真的就抛弃了IDE,流行纯手工呢!

云风把字体调大了啊

有意思···

负责在所有平台上测试的人应该是做测试的吧,如果让dev也来搞显然会让负担不平衡。

http://chuang.csdn.net/page/d2566b59-3356-42fa-870d-926a06a95b1d

呵呵~ 这个传说,很有意思,是否真的?

你们公司的代码可以在家里电脑上checkout吗?还是不是公司的代码?

win2003 下都是运行正常的。

最新的Win7 SDK文档中改成[in, out]了

似乎这个问题,用C++就不会碰到,因为C++的const指针不能隐式转换为非const指针。

直接用char的话,最好直接写ExtractAssociatedIconA这样的API,这样就算宏设置有变也能编译通过

写漏了:TCHAR szCommandLine[] = _T("xxx.exe");

碰到过。不晓得是不是类似的。
另开进程,处理数据的时候:环境vs2008 + vista
CreateProcess(NULL,_T("xxx.exe"),...);
运行错误,调试CreateProcess执行错误。
修正:
TCHAR szCommandLine = _T("xxx.exe");
CreateProcess(NULL,szCommandLine ,....);才运行成功。

ssh -D的确还是不错的...我的cvs也只能用ssh的通道,否则只能在测试机器上跑,不能本地修改了

人手不足 呵呵。也无力调用公司测试团队。

另外办公室的机器采购的比较早,都是预装的 XP ,或自己装的 ubuntu/freebsd 等开源系统 ,没有特别花经费购买 vista 。

比较好奇,为什么发布前不在所有支持的平台上作测试?在我们公司里这首先是dev的责任。

我们的系统里全部没用 TCHAR ,所以就直接用 char 了。

是不是改成:
wchar_t filename[]=L"loader.exe";
更合适?

恩,俺使用vpn ,比ssh forward 速度要好些

Post a comment

非这个主题相关的留言请到:留言本