修正TaskManagerEx2.0的一个BUG

摘要:简要介绍一个Windows 任务管理器(Task Manager)功能扩展工具TaskManagerEx,同时指出了TaskManagerEx 2.0的一个与中文文件名有关的BUG并修正了这个BUG。

关键字:任务管理器 Task Manager 扩展

从Windows NT开始,Microsoft给Windows提供了一个功能强大的任务管理器(Task Manager),任务管理器功能强大,不仅能够查看程序运行过程中的资源、句柄、内存以及CPU占有率等计量信息,还能够中止正在运行的程序,任务管理器成为Windows最受欢迎的组件之一。虽然任务管理器功能多多,但还是有人觉得应该再多一些功能,Zoltan Csizmadia就是这些人中的一个。此君于2001年愚人节那天在CodeGuru网站上发表了一篇名为“Task Manager Extension”的文章,发布了一个他为任务管理器定制的扩展插件:TaskManagerEx。说TaskManagerEx是一个任务管理器插件其实有些牵强,因为Windows的任务管理器并没有提供扩展插件的接口,这个TaskManagerEx是用钩子强行“塞”任务管理器的,用黑客们的话说就是任务管理器被“Hacking”了。这个所谓的插件给Windows任务管理器添加了一个“Extension”菜单,添加了进程模块查看、句柄信息查看、窗口信息查看以及文件信息查看等功能,在2005年5月,Sergey Kolomenkin(可能是个俄国人?)在TaskManagerEx的基础上发布了2.0版本,添加了包括“memory map”在内的很多功能,大家可以通过以下链接查看Sergey Kolomenkin在CodeProject上发表的原文:http://www.codeproject.com/system/Task_Manager_Extension.asp。这片文章和Zoltan Csizmadia发表在CodeGuru上的那篇文章一样短小精悍,言简意赅,毕竟说得再多也没有,看代码才是硬道理,看看下面图片你就知道为什么TaskManagerEx如此受欢迎了:



不过Sergey Kolomenkin发布的这个2.0版本存在一个严重的BUG,使得TaskManagerEx在处理含有中文、韩文以及日文这样的Unicode字符串时丢失数据,最终的结果就是无法正常显示包含中文、韩文以及日文的文件名。出现这个错误的原因是Sergey Kolomenkin修改了SystemInfoUtils::LPCWSTR2CString()的实现代码(使用WideCharToMultiByte转换字符串),Sergey Kolomenkin的代码是这样的:

// From wide char string to CString
void SystemInfoUtils::LPCWSTR2CString( LPCWSTR strW, CString& str )
{
#ifdef UNICODE
// if it is already UNICODE, no problem
str = strW;
#else

ULONG len = wcslen(strW) + 1;
TCHAR* pBuffer = new TCHAR[ len ];
if( pBuffer == NULL )
{
ASSERT( FALSE );
str.Empty();
return;
}

int res = WideCharToMultiByte( CP_ACP, 0, strW, len, pBuffer, len, NULL, NULL );
if( res == 0 )
{
pBuffer[0] = _T('/0');
}

str = pBuffer;

delete [] pBuffer;
#endif
}

当程序采用非Unicode方式编译时,Sergey Kolomenkin采用wcslen(strW) + 1计算出转换后的字符串长度,并根据此值动态分配了存储控件,然后使用WideCharToMultiByte进行转换。代码处理英文字符串时可以正常工作,但是当字符串中含有中、日、韩这样的双字符文字时就会出错,主要原因是wcslen(strW) + 1计算出的长度不足以存放转换后的字符串,于是WideCharToMultiByte函数返回0,导致pBuffer[0] = _T('/0');被执行,于是pBuffer就成了空字符串。以下是出现BUG时的效果图:

图中加亮的一行是一个文件句柄(0x3D8),是Acrobat Reader打开了一个含有中文名的文件D:/100 个智力小游戏.pdf,由于上面提到的BUG导致文件名无法正常显示。现在将这个BUG fix,修改后的LPCWSTR2CString函数如下:

void SystemInfoUtils::LPCWSTR2CString( LPCWSTR strW, CString& str )
{
#ifdef UNICODE
// if it is already UNICODE, no problem
str = strW;
#else

ULONG len = wcslen(strW) * 2 + 1;
TCHAR* pBuffer = new TCHAR[ len ];
if( pBuffer == NULL )
{
ASSERT( FALSE );
str.Empty();
return;
}

int res = WideCharToMultiByte( CP_ACP, 0, strW, -1, pBuffer, len, NULL, NULL );
pBuffer[res] = _T('/0');

str = pBuffer;

delete [] pBuffer;
#endif
}

修改后再加载TaskManagerEx,就可以看到这个文件名了:


我已经在CodeProject上报告了这个BUG,呵呵,应该快有新版本出来了。

你可能感兴趣的:(manager)