You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

挂钩DLL中播放资源音频导致游戏无法启动的问题排查

挂钩DLL播放内置音频资源导致游戏无法启动的故障排查

问题场景

我需要在挂钩的DLL中播放其内置资源里的音频文件,使用的代码为:

PlaySoundA(MAKEINTRESOURCEA(IDR_WAVE1), hModule, SND_RESOURCE);

我的DLL代码

HINSTANCE m_hinst_dll = nullptr;
extern "C" UINT_PTR mProcs[17]{ 0 };
 
LPCSTR import_names[] = {
    "GetFileVersionInfoA",
    "GetFileVersionInfoByHandle",
    "GetFileVersionInfoExA",
    "GetFileVersionInfoExW",
    "GetFileVersionInfoSizeA",
    "GetFileVersionInfoSizeExA",
    "GetFileVersionInfoSizeExW",
    "GetFileVersionInfoSizeW",
    "GetFileVersionInfoW",
    "VerFindFileA",
    "VerFindFileW",
    "VerInstallFileA",
    "VerInstallFileW",
    "VerLanguageNameA",
    "VerLanguageNameW",
    "VerQueryValueA",
    "VerQueryValueW"
};
 
void setupWrappers()
{
    CHAR sys_dir[MAX_PATH];
    GetSystemDirectoryA(sys_dir, MAX_PATH);
    char buffer[MAX_PATH];
    sprintf_s(buffer, "%s\\version.dll", sys_dir);
    m_hinst_dll = LoadLibraryA(buffer);
    for (int i = 0; i < 17; i++) {
        mProcs[i] = reinterpret_cast<UINT_PTR>(GetProcAddress(m_hinst_dll, import_names[i]));
    }
}
 
extern "C" void GetFileVersionInfoA_wrapper();
extern "C" void GetFileVersionInfoByHandle_wrapper();
extern "C" void GetFileVersionInfoExA_wrapper();
extern "C" void GetFileVersionInfoExW_wrapper();
extern "C" void GetFileVersionInfoSizeA_wrapper();
extern "C" void GetFileVersionInfoSizeExA_wrapper();
extern "C" void GetFileVersionInfoSizeExW_wrapper();
extern "C" void GetFileVersionInfoSizeW_wrapper();
extern "C" void GetFileVersionInfoW_wrapper();
extern "C" void VerFindFileA_wrapper();
extern "C" void VerFindFileW_wrapper();
extern "C" void VerInstallFileA_wrapper();
extern "C" void VerInstallFileW_wrapper();
extern "C" void VerLanguageNameA_wrapper();
extern "C" void VerLanguageNameW_wrapper();
extern "C" void VerQueryValueA_wrapper();
extern "C" void VerQueryValueW_wrapper();
 
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            setupWrappers();
 
            PlaySoundA(MAKEINTRESOURCEA(IDR_WAVE1), hModule, SND_RESOURCE);

            break;
 
        case DLL_PROCESS_DETACH:
 
            break;
    }
    return TRUE;
}

已做排查

  • 移除PlaySoundA调用后,DLL可正常工作
  • 用空桌面项目测试该PlaySoundA代码,能正常播放音频
  • 在DLL中使用以下代码播放外部音频文件也正常:
    sndPlaySoundA("mnu_back.wav", SND_FILENAME | SND_ASYNC);
    

可能的故障原因

  1. 资源ID不匹配或未正确嵌入:检查DLL资源脚本中IDR_WAVE1是否对应正确的WAV资源,且编译时资源已成功嵌入DLL。游戏进程加载DLL时,若找不到指定资源,PlaySoundA可能触发未处理错误导致进程崩溃。
  2. DLLMain阶段调用风险:DLL_PROCESS_ATTACH阶段进程初始化尚未完成,调用PlaySoundA这类依赖系统音频服务的API可能引发死锁或初始化冲突——系统音频服务可能还未完成加载,此时调用会导致进程阻塞或崩溃。
  3. 资源加载上下文异常:虽然DllMain的hModule通常指向当前DLL模块句柄,但某些挂钩场景(如注入时机过早)下,模块的资源表可能未完全初始化,导致无法读取资源。
  4. 缺少异步播放标志:当前调用未加SND_ASYNC,PlaySoundA会同步播放音频,在DLLMain阶段同步操作可能阻塞进程初始化流程,导致游戏启动超时或崩溃。可尝试修改代码:
    PlaySoundA(MAKEINTRESOURCEA(IDR_WAVE1), hModule, SND_RESOURCE | SND_ASYNC);
    
  5. 游戏进程环境限制:游戏进程可能运行在沙箱、低权限等受限环境中,不允许从DLL资源加载音频,而外部文件播放不受限制;或者游戏进程禁用了部分系统音频API的资源加载路径。

内容的提问来源于stack exchange,提问作者marcoluca987

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:50:44