在不调试的情况下解决下面的问题,说明你的思维调试能力又进阶了。
问题
我在调用 FormatMessage 函数加载一个插入的资源字符串,由于某种未知的原因,它没能按预期那样工作。
我要加载的字符串类似于这样的 “Blah blah blah %1. Blah blah blah.”
FormatMessage 调用失败了,通过 GetLastError,我得到了具体的错误代码:
ERROR_RESOURCE_TYPE_NOT_FOUND
代码如下:
>> 请移步至 www.topomel.com 以查看图片 <<
给你第一个提示:请特别注意上面代码中的 IDS_MY_CUSTOM_MESSAGE 参数。
第二个提示:”IDS_” 这个标识,你会想到什么?
以 “IDS_” 开头的资源,一般都是字符串资源,而不是消息资源标识。关于消息资源标识符的命名约定没有达成强烈的共识,尽管我曾经见过 “MSG_” 这样的资源标识前缀,部分原因是几乎没有人使用消息资源!
我不明白为什么将它们添加到 Win32 中,因为已经有一种在资源中嵌入字符串的方法,即字符串资源。
这就是你得到
ERROR_RESOURCE_TYPE_NOT_FOUND 的原因。模块中没有消息资源。如果不打算使用消息资源,则必须使用 FORMAT_MESSAGE_FROM_STRING 标志并显式传递格式字符串。
>> 请移步至 www.topomel.com 以查看图片 <<
我还对最终参数进行了轻微更改。使用
FORMAT_MESSAGE_ARGUMENT_ARRAY 时,最后一个参数必须是 DWORD_PTRs 数组。(必须将参数强制转换为 va_list* 才能使编译器满意。)
碰巧原始代码避开了这个错误,因为 sizeof(DWORD_PTR) == sizeof(LPTSTR) 并且它们都具有相同的对齐要求。
另一方面,如果插入是 DWORD,则传递 (va_list*)&dwValue 肯定是错误的,如果您运气不好,可能会崩溃。(多测试几次就知道了)
总结
有很多技术你可能一辈子都不会用到,但它确实在那里。
一小块,一小块的,将它们搞懂。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Psychic debugging: Why does FormatMessage say the resource couldn’t be found?》