我们想列出嵌入在资源专用库(DLL)中的消息的内容(键/值对)
资源库定义为MSDN中指定的。
mc -s EventLogMsgs.mc
rc EventLogMsgs.rc
link /DLL /SUBSYSTEM:WINDOWS /NOENTRY /MACHINE:x86 EventLogMsgs.Res
EventLogMsgs示例。MC可能是:
; // - Event categories -
; // Categories must be numbered consecutively starting at 1.
; // ********************************************************
MessageId=0x1
Severity=Success
SymbolicName=INSTALL_CATEGORY
Language=English
Installation
.
MessageId=0x2
Severity=Success
SymbolicName=QUERY_CATEGORY
Language=English
Database Query
.
...
我们尝试使用EnumResourceTypes() Win32 API如下:
...
HMODULE hMod=NULL;
hMod = LoadLibraryA( "C:\temp\EventLogMsgs.dll" );
if (hMod != NULL)
{
EnumResourceTypes( hMod, (ENUMRESTYPEPROC)TypesCallback, 0) ;
FreeLibrary(hMod);
}
...
BOOL WINAPI TypesCallback( HMODULE hModule, LPTSTR lpType, LONG lParam )
{
char buffer[100];
if ((ULONG)lpType & 0xFFFF0000)
sprintf( buffer, "%sn", lpType);
else
sprintf(buffer, "%un", (USHORT)lpType);
cout << "Type: " << buffer << std::endl;
EnumResourceNames( hModule, lpType, (ENUMRESNAMEPROC)NamesCallback, 0 );
return true;
}
BOOL WINAPI NamesCallback( HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam )
{
char buffer[100];
if ((ULONG)lpName & 0xFFFF0000)
sprintf(buffer,"%sn", lpName);
else
sprintf(buffer, "%un",(USHORT)lpName);
cout << "Name: " << buffer << std::endl;
return true;
}
结果是资源类型及其"名称/标识符"的高级列表,例如
...
Type: 11
Name: 1
Type: 16
Name: 1
Type: 24
Name: 2
...
11 (RT_MESSAGETABLE)是消息表资源类型(参见所有资源类型)
理想情况下,我们希望在资源库中列出所有实际消息的符号名称和标识符。谢谢
您已经枚举了模块中的资源,该模块告诉您特定类型的每个资源的名称。完成这些后,需要加载资源以检查其内容。在您的示例中,您需要命名为1
的类型为RT_MESSAGETABLE
的资源。
您现在需要使用FindResource
, LoadResource
和LockResource
来获得指向消息表结构开始的指针。然后可以使用MESSAGE_RESOURCE_DATA
结构体,再使用MESSAGE_RESOURCE_BLOCK
和MESSAGE_RESOURCE_ENTRY
来解包消息表的内容。这篇代码项目文章详细介绍了这个过程。
下面是一个相当简单的C程序,它枚举消息表:
#include <windows.h>
#include <stdio.h>
int ProcessBlock(MESSAGE_RESOURCE_DATA* data, MESSAGE_RESOURCE_BLOCK* block)
{
MESSAGE_RESOURCE_ENTRY* entry = (MESSAGE_RESOURCE_ENTRY*) ((unsigned char*)data + block->OffsetToEntries);
for (DWORD id = block->LowId; id <= block->HighId; id++)
{
if (entry->Flags == 0x0001) // wide char
printf("%d, %ls", id, entry->Text);
else if (entry->Flags == 0x0000) // ANSI
printf("%d, %s", id, entry->Text);
entry = (MESSAGE_RESOURCE_ENTRY*) ((unsigned char*)entry + entry->Length);
}
return 1;
}
int main(void)
{
HMODULE hMod = LoadLibrary("C:\desktop\EventLogMsgs.dll");
if (hMod == NULL) return 1;
HRSRC hRsrc = FindResource(hMod, MAKEINTRESOURCE(1), RT_MESSAGETABLE);
if (hRsrc == NULL) return 1;
HGLOBAL hGlobal = LoadResource(hMod, hRsrc);
if (hGlobal == NULL) return 1;
MESSAGE_RESOURCE_DATA* data = (MESSAGE_RESOURCE_DATA*)LockResource(hGlobal);
if (data == NULL) return 1;
for (DWORD block = 0; block < data->NumberOfBlocks; block++)
if (!ProcessBlock(data, &data->Blocks[block]))
return 1;
return 0;
}
<>之前1、安装2、数据库查询3、数据刷新1000,我的应用程序消息文本,英文,消息id 1000,从%1调用。1002,我的通用信息信息是英文的,对于消息id 1002。%%5002的更新周期已经完成。5001,样例事件日志5002年,SVC_UPDATE.EXE-2147482647,我的应用程序消息文本,英文,消息id 1001,从%1调用。-2147482645,我的通用英文警告消息,对于消息id 1003,从%1调用。-2147482643,刷新操作没有完成,因为无法建立到服务器%1的连接。之前
请原谅我糟糕的C语言。C和c++都不是我很精通的语言。但是,代码至少会向您展示如何提取所需的信息。