最近,我们的一些客户从他们的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库也可能无法使用静态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文件编译生成了未解析的外部符号。此实用程序带有处理未解析符号的方法,但在Symbol Finder或Advanced Conversion Options中输入任何内容都会崩溃。查看最新发行说明(3.00),我发现他们添加了对Vista的支持而没有提及Windows 7.此外,这对64位dll也不起作用。
我尝试过另一种方法是更改初始化序列以使用此链接中描述的非注册COM DLL:Use COM Object from DLL 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。使用此处描述的流程:DLL redirection using manifests XAudio2Create仍然失败。我没有一个强有力的策略来确定清单的错误。我还没有找到关于dll重定向清单的最新文档。从这个声音来看,这主要用于加载特定的DLL版本。我不认为DLL重定向是我需要的方法,因为在exe的同一目录中已经存在XAudio2_7的本地副本,这意味着它应该优先于系统目录中的XAudio2_7,具体如下:msdn.microsoft.com /en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
注意:我删除了某些地址的超链接,因为我没有足够的信誉点来发布超过2个链接。