2

最近,我们的一些客户从他们的 C:/Windows/System32 目录中丢失了他们的 XAudio2_7.dll,现在他们听不到任何音频。通常重新安装 DirectX 或注册 dll 就足以解决此问题,但我们正在寻找不需要管理员权限的解决方案。这适用于 Windows 7。应用程序是用 CPP 编写的,其中一些是 32 位的,其余​​的是 64 位的。

在 exe 的同一目录中有 XAudio2_7.dll 的本地副本,但除非该 dll 已注册,否则不会加载,因为它是 COM dll。为当前用户注册(使用“Regsvr32.exe /n /i:user XAudio2_7.dll”)不起作用,因为 dll 没有实现所需的接口“DllInstall”。

我尝试过的一种方法是静态链接 XAudio 的 .lib,而不是使用动态链接。Microsoft 不会随 DirectX SDK 分发 XAudio2_7.lib。“没有任何版本的 DirectX SDK 包含 xaudio2.lib 导入库。DirectX SDK 版本使用 COM 来创建新的 XAudio2 对象。” msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2create%28v=vs.85%29.aspx

当然,这表明即使我创建了一个静态 XAudio 库,也可能无法使用它,因为它听起来像是依赖于其他库中定义的外部对象。如果我的假设不正确,它仍然值得测试。

按照此链接中提到的步骤:adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/

我没有用这种方法走得很远。除了过时的文章之外,还有一些问题。博客中的 MS 链接提到这是针对 32 位 dll 的。即使对于 32 位 dll,dumpbin 也不起作用,因为它只导出接口函数。转储文件 C:\XAudioTest\32Bit\XAudio2_7.dll

File Type: DLL

  Section contains the following exports for xaudio2.dll

    00000000 characteristics
    4C064181 time date stamp Wed Jun 02 07:33:21 2010
        0.00 version
           1 ordinal base
           4 number of functions
           4 number of names

    ordinal hint RVA      name

          1    0 00030AA0 DllCanUnloadNow
          2    1 00031150 DllGetClassObject
          3    2 00031470 DllRegisterServer
          4    3 000314D0 DllUnregisterServer

  Summary

        C000 .data
        1000 .no_bbt
        4000 .reloc
        1000 .rsrc
       7B000 .text

后来,我从另一篇 MSDN 文章中找到了这句话。“COM 标准要求 COM DLL 导出 DllCanUnloadNow、DllGetClassObject、DllRegisterServer 和 DllUnregisterServer。通常它们不会导出任何其他内容。这意味着您无法使用 dumpbin.exe 获取 COM 对象或方法信息。” msdn.microsoft.com/en-us/library/aa446532.aspx

我还尝试过使用声称它能够从 COM dll 创建 .lib 的第三方程序。www.binary-soft.com/dll2lib/dll2lib.htm

虽然这确实生成了一个 32 位的 .lib 文件,但使用 lib 文件进行编译会生成未解析的外部符号。此实用程序确实带有处理未解析符号的方法,但在符号查找器或高级转换选项中输入任何内容都会崩溃。查看最新的发行说明 (3.00),我发现他们添加了对 Vista 的支持,但没有提及 Windows 7。这也不适用于 64 位 dll。

我尝试过另一种方法是更改​​初始化序列以使用此链接中描述的未注册 COM DLL: 使用 DLL 中的 COM Object without register 初始化代码类似于以下内容:

    HMODULE audioLib = LoadLibrary(TEXT("XAudio2_7.dll"));
    if (audioLib == NULL)
    {
        debugf(TEXT("Failed to create COM object.  Unable to load XAudio2_7.dll library.  GetLastError:  %d"), GetLastError());
        return;
    }

    typedef HRESULT (WINAPI* Function_DllGCO) (REFCLSID, REFIID, LPVOID*);
    Function_DllGCO processAddress = (Function_DllGCO)GetProcAddress(audioLib, "DllGetClassObject");

    if (processAddress == NULL)
    {
        debugf(TEXT("COM DLL failed to find the process address to interface function 'DllgetClassObject' within the XAudio2_7.dll.  GetLastError:  %d"), GetLastError());
        return;
    }

    class __declspec(uuid("{5a508685-a254-4fba-9b82-9a24b00306af}")) xAudioGUID;
    REFCLSID classID = __uuidof(xAudioGUID);

    class __declspec(uuid("{00000001-0000-0000-c000-000000000046}")) classFactoryGUID;
    REFIID classFactoryID = __uuidof(classFactoryGUID);

    IClassFactory* ClassFactory = NULL;
    if (processAddress(classID, classFactoryID, reinterpret_cast<LPVOID*>(&ClassFactory)) != S_OK)
    {
        debugf(TEXT("Failed to execute function pointer to DLLGetClassObject.  GetLastError:  %d"), GetLastError());
    return;
    }

    class __declspec(uuid("{00000000-0000-0000-C000-000000000046}")) unknownGUID;
    REFIID unknownID = __uuidof(unknownGUID);
    if (ClassFactory->CreateInstance(NULL, unknownID, reinterpret_cast<void**>(&ClassFactory)) != S_OK)
    {
        debugf(TEXT("Class factory for XAudio2_7 failed to create an object instance.  GetLastError:  %d"), GetLastError());
        ClassFactory->Release();
        return;
    }

    if( XAudio2Create( &XAudio2, 0, AUDIO_THREAD) != S_OK ) //Fails here with error number:  1008 (An attempt was made to reference a token that does not exist.)
    {
        debugf( NAME_Init, TEXT( "Failed to create XAudio2 interface:  GetLastError:  %d" ), GetLastError());
        return;
    }
    //Do other things

传递的所有 WinAPI 函数调用不包括 XAudio2Create 函数。我不确定为什么 XAudio2Create 不使用从工厂创建的对象,而且我不知道我需要做什么才能让它使用该对象。我仍在调查我能在这里做什么,但调试封闭源代码库很困难。

在我了解 COM DLL 之前,我尝试过的一种方法是使用 DLL 重定向来强制应用程序使用特定的 DLL。使用此处描述的过程: 使用清单 XAudio2Create的DLL 重定向仍然失败。我没有强有力的策略来确定清单有什么问题。我也没有找到关于 dll 重定向清单的最新文档。从这听起来是这主要用于加载特定的 DLL 版本。我不认为 DLL 重定向是我需要的方法,因为在 exe 的同一目录中已经有 XAudio2_7 的本地副本,这意味着它应该优先于系统目录中的 XAudio2_7,根据:msdn.microsoft.com /en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx

注意:我删除了一些地址的超链接,因为我没有足够的信誉点来发布超过 2 个链接。

4

1 回答 1

2

您是否尝试过免注册激活

于 2016-01-14T18:09:07.160 回答