一番良い方法は、
1.SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)を発行する
(これが発行できれば、WinAPIやCOM I/F によって、パス指定なしDLLのロードが発生しても、exeフォルダのDLLがロードされることはなくなります)
しかし、KB2533623が入っていないWin7やVistaではこのAPIがありません。
その場合、少し面倒ですが下記の方法が無難です。
(いくつかの汎用インストーラはこの形)
2-1.起動されると同時に、自分自身(実行ファイル)を新規に作ったフォルダにコピー
2-2.(カレントを新規フォルダとして)コピーした実行ファイルを起動し、そこから本来のインストール動作を実行
上記の方法以外に、予め何をロードするかが判っていれば、
3.それらを事前にパス指定でLoadLibraryしておくこと
により、その後、パス指定なしのLoadLibraryが発生しても、すでにロードされたモジュールが使われるようになります。
(しかし、3の方法ではどのDLL群をロードするか、事前に確定することが難しい(WinAPI等の内部実装に依存)という点を考慮する必要があります)
補足(2017/08/06追記)
1.上記2-1でテンポラリ名を乱数生成して作成する場合、下記に注意します。
STL の std::random_device()を利用すると、内部で"cryptbase.dll"がパスなしでロードされます。
従い、std::random_device()を利用する前に、事前にパス指定でcryptbase.dllをロードしておきます。
(なお、CryptGenRandom APIを使った場合も、類似問題があるのでご注意)
2.起動からWinMainに到達するまでに、exeフォルダDLLが優先してロードされるDLLに注意します。
リンカやpragmaに指定しており、KnownDLLでないDLL全般が該当します。(手元で確認している例では、winmm.dll, mpr.dll など)
解決には「DLL遅延読み込み」を使います。
リンカの「DLL遅延読み込み(/DELAYLOAD)」に winmm.dll; mpr.dll 等を指定した上で、WinMain直後に上記の「今回の問題を考慮した対策方法」の1or2を行います。
3.いずれの場合でも、
デバッガで起動から終了までのDLLロード状況を確認して、対策が正しく機能しているか確かめることをお勧めします。(
*4)