3

次のコードを使用して、C:\Windows\System32\ フォルダーにプリンター ドライバーと共にインストールされた DLL を読み込もうとしています。

LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");

GetLastError()「指定されたモジュールが見つかりませんでした」と報告しています。DLL を System32 フォルダー (たとえば、C:\SomeFolder\MagAPI.dll) の外に移動すると、正常に読み込まれるため、DLL 自体に問題があるようには見えません。アプリケーションの読み込みをブロックしている可能性のある奇妙な Windows セキュリティ機能はありますか? それしか思い浮かばないのですが、決定的な答えが見つかりません。

ShowSnaps からのデバッグ出力は次のとおりです。これは、失敗している場所を示しています。

1a8c:1fd4 @ 19006756 - LdrLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - INFO: Loading DLL C:\Windows\system32\MagAPI.dll from path C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpSearchPath - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - ENTER: DLL name: C:\Windows\system32\MagAPI.dll
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpSearchPath - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpLoadDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrLoadDll - RETURN: Status: 0xc0000135
4

1 に答える 1

6

アプリケーションが 32 ビットであると述べているため、ロードする DLL も 32 ビットである必要があります。

失敗する理由として考えられるのLoadLibrary()は、64 ビット版の Windows を実行しているのに、プリンター ドライバーが問題の 32 ビット DLL をSystem32フォルダーではなくフォルダーに誤ってインストールしたことSysWOW64です。

背景: Windows の 64 ビット エディションでは、64 ビット DLL はSystem32フォルダーに入れられ、32 ビット DLL はSysWOW64フォルダーに入れられます。逆のように聞こえるかもしれませんが、名前に惑わされないでください。フォルダの名前は、下位互換性の理由から付けられています。フォルダはアプリケーションに対して透過的であると想定されていSysWOW64ます: Windows にはファイル システム リダイレクトと呼ばれる機能がSystem32あり、DLL が実際に中に入っていSysWOW64ます。

一方、LoadLibrary()間違ったフォルダー内に配置された DLL のロードを単に拒否します。これは、おそらく見られる動作です。

問題の実際の解決策は、プリンターの製造元に連絡して、ドライバー インストーラーがその DLL を 64 ビット エディションの Windows で間違ったフォルダーに配置していることを知らせることです。彼らがこれを修正した場合、アプリケーションは既存のコードを変更しなくても正しく動作するようになります。

それまでの間、次のようにして問題を回避できるはずです。

  1. %windir%\SysnativeDLL をロードする前に、管理できる既知のフォルダーにDLL をコピーします。(内部に一意の名前のフォルダーを作成し、%TEMP%そのフォルダーに DLL をコピーすることをお勧めします)。注:は、 Windows の 64 ビット版にSysnativeあるネイティブ システム フォルダーにマップされる特別なエイリアスです。System32
  2. 呼び出しLoadLibrary()て、手順 1 で作成した DLL のコピーのパスを渡します。
  3. DLL の使用が終了したら、DLL をアンロードし、手順 1 で作成したコピーを削除します。

64 ビット Windows XP をサポートする必要がある場合、上記の回避策は機能しない可能性があります。これは、Sysnativeエイリアスが Windows Vista 以降でのみ機能することが文書化されているためです。別の回避策は、ファイル システムのリダイレクトを手動でバイパスすることです。

  1. を呼び出して、ファイル システムのリダイレクトを一時的に無効にしますWow64DisableWow64FsRedirection()。これにより、アプリケーションは実際に何が入っているかを確認できますSystem32
  2. DLL を、System32管理している既知のフォルダーにコピーします。
  3. を呼び出して、ファイル システムのリダイレクトを再度有効にしますWow64RevertWow64FsRedirection()
  4. 呼び出しLoadLibrary()て、手順 2 で作成した DLL のコピーのパスを渡します。
  5. DLL の使用が完了したら、DLL をアンロードし、手順 2 で作成したコピーを削除します。

DLL をコピーせずに作業を開始Wow64DisableWow64FsRedirection()するために呼び出すことを考えている場合は、気にしないでください。 はその設定に注意を払いません。(実際に試してみました。)LoadLibrary()LoadLibrary()

詳細:ファイル システム リダイレクター

于 2013-08-31T23:11:34.587 に答える