最近、一部のクライアントで C:/Windows/System32 ディレクトリから XAudio2_7.dll が失われ、音声が聞こえなくなりました。この問題を解決するには、DirectX を再インストールするか、DLL を登録するだけで十分ですが、管理者権限を必要としない解決策を探しています。これは Windows 7 用です。アプリケーションは CPP で記述されており、一部は 32 ビットで残りは 64 ビットです。
exe の同じディレクトリ内に XAudio2_7.dll のローカル コピーがありますが、それは COM dll であるため、その dll が登録されていない限り読み込まれません。現在のユーザーの登録 (「Regsvr32.exe /n /i:user XAudio2_7.dll」を使用) は、dll が必要なインターフェイス「DllInstall」を実装していないため、機能しません。
私が試したアプローチの 1 つは、動的リンクを使用する代わりに、XAudio の .lib を静的にリンクすることです。Microsoft は XAudio2_7.lib を DirectX SDK と共に配布していません。「xaudio2.lib インポート ライブラリを含む DirectX SDK のバージョンはありません。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 ファイルを使用してコンパイルすると、未解決の外部シンボルが生成されました。このユーティリティには、未解決のシンボルを処理するメソッドが付属していますが、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
XAudio2Create 関数を除くすべての WinAPI 関数呼び出しが渡されました。XAudio2Create がファクトリから作成されたオブジェクトを使用しない理由がわかりません。また、そのオブジェクトを使用するために何をする必要があるのかもわかりません。ここで何ができるかはまだ調査中ですが、クローズド ソース ライブラリをデバッグするのは困難です。
COM DLL について知る前に、DLL リダイレクトを使用してアプリケーションに特定の DLL を強制的に使用させる方法を試しました。ここで説明されているプロセスの使用: マニフェスト XAudio2Createを使用した DLL リダイレクトはまだ失敗しました。マニフェストの何が問題なのかを特定するための強力な戦略はありません。また、dll リダイレクトのマニフェストに関する最新のドキュメントもあまり見つかりませんでした。この音から、これは主に特定の DLL バージョンをロードするために使用されます。msdn.microsoft.comによると、exeの同じディレクトリ内にXAudio2_7のローカルコピーが既に存在するため、DLLリダイレクトは必要な方法ではないと思います。つまり、システムディレクトリ内のXAudio2_7よりも優先する必要があります。 /en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
注: 2 つ以上のリンクを投稿するのに十分な評価ポイントがないため、一部のアドレスのハイパー リンクを削除しました。