FindResource() 函数失败,尽管资源存在
Posted
技术标签:
【中文标题】FindResource() 函数失败,尽管资源存在【英文标题】:FindResource() function fails although resource exists 【发布时间】:2016-01-28 13:28:17 【问题描述】:我正在尝试使用 Win32 FindResource() 函数将嵌入式资源加载到缓冲区中。 我在 Visual Studio 2015 IDE 中添加资源编译时间:
正如您使用 CFFexplorer 或 ResHacker 等 PE 编辑器所见,资源已正确添加:
当我尝试使用 FindResource() 函数在运行时加载它时,即在 DLL 项目开始时出现问题:
INT WINAPI DllMain( HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpReserved )
HRSRC ResLocation = 0;
switch( dwReason )
case DLL_PROCESS_ATTACH:
// Show debug console
AllocConsole();
freopen("CONOUT$", "w", stdout);
//Locate our resource
ResLocation = FindResource(hInstDLL, "RESFILE", "RESFILE");
// FindResource returns NULL with error 1813: ERROR_RESOURCE_TYPE_NOT_FOUND
printf("TEST RESULT: reslocation: %i error %i\n", ResLocation, GetLastError());
StartProc();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
return 1;
FindResource 返回 NULL,错误 1813:ERROR_RESOURCE_TYPE_NOT_FOUND。 关于为什么它无法加载资源的任何想法? 谢谢
【问题讨论】:
你应该不在DllMain
做所有这些! AllocConsole
是一个明显的禁忌。
为什么不呢?请您详细说明一下
@FlavioM.Foglia:DLLMain 不应该做任何可能导致加载更多代码、同步对象被锁定等的事情。msdn.microsoft.com/en-us/library/windows/desktop/…
阿德里安报道了它。一般规则是在DllMain
中基本上什么都不做,只是为了安全起见。该文档包含一个明确禁止的列表,但调用任何复杂的 API 或第三方代码本质上是棘手的,因为您无法知道 它们 做什么。目标是保持DllMain
为空存根,对所有内容使用延迟初始化。如果您绝对需要做更多事情,请让您的 DLL 提供并导出应用程序将调用的 Initialize
(或类似)函数。 Windows 库都是这样做的,例如 COM、GDI+ 等。
【参考方案1】:
我发现了问题所在。
有另一个可执行文件在运行时在同一个 dll 上写入了另一个资源。 它使用 BeginUpdateResource() 完成此操作。
问题出在 BeginUpdateResource() 第二个参数,它设置为 true:添加新资源时,它会删除我在设计时添加的旧资源。将此参数设置为false,解决了我的问题。
【讨论】:
【参考方案2】:FindResource()/LoadResource() 是 AFAIK 不是查找/加载整个资源“文件”(事实上没有这样的文件,资源嵌入在 dll 中),而是一个特定的资源(字符串,资源 src 文件指定的位图、图标等)。
“RESFILE”不是允许的资源类型,列表见ResourceTypes。
【讨论】:
是的,我知道,但也可以添加和加载可能包含任意数据的自定义命名资源【参考方案3】:看来你的第三个参数是错误的。
来自 MSDN:
HRSRC WINAPI FindResource(
_In_opt_ HMODULE hModule,
_In_ LPCTSTR lpName,
_In_ LPCTSTR lpType
);
lpType [输入]
资源类型。或者,而不是 一个指针,这个参数可以是 MAKEINTRESOURCE(ID),其中 ID 是 给定资源类型的整数标识符。对于标准资源 类型,请参阅Resource Types。有关详细信息,请参阅备注 下面的部分。
使用上面的链接查找您的资源类型并使用它而不是“RESFILE”。
例如
ResLocation = FindResource(hInstDLL, "RESFILE", MAKEINTRESOURCE(RT_VERSION));
【讨论】:
试过了,但我收到错误 1814:ERROR_RESOURCE_NAME_NOT_FOUND。虽然我正确地定义了它并且资源被正确地添加到 PE 文件中。 ' #define IDR_RCDATA1 104 ResLocation = FindResource(hInstDLL, MAKEINTRESOURCE(IDR_RCDATA1), MAKEINTRESOURCE(RT_RCDATA));' @FlavioRT_VERSION
是一个已经定义为MAKEINTRESOURCE(16)
的宏,因此无需再次将其传递给MAKEINTRESOURCE
以上是关于FindResource() 函数失败,尽管资源存在的主要内容,如果未能解决你的问题,请参考以下文章
将EXE作为资源,然后在释放到磁盘上并运行该exe程序(使用了FindResource,LoadResource,然后用CFile写成一个文件)
如何使用 Windows Native API 访问 PE 资源?
Jackson 因“无法构造 WorkpoolId 的实例(尽管至少存在一个 Creator)而失败:没有 int/Int-argument 构造函数/工厂”