読者です 読者をやめる 読者になる 読者になる

標準出力

新しいもの、変わらないこと 自分の頭を通して考えてみました (stdout)

Windows の共有ライブラリロード時のサーチパスの優先順位

Linux の場合LD_LIBRARY_PATHに依るけどWindowsの場合は、
[1] アプリケーションがロードされたディレクトリ
[2] System directory
[3] 16bit system directory
[4] Windows directory
[5] カレントディレクトリ
[6] 環境変数PATH

の順らしいです。ということで検証してみた。今回は、検証用の自分自身が配置されている場所を返すプロシージャを含む"studyTest.dll"とそれを用いるコードを書いて確認してみた。

dllを使用する側のプロセス生成時のカレントディレクトリを起点としたディレクトリとファイルツリーは、下記のようになっている。

.\
├─bin
│      studyTest.dll
│      useDll.exe
│    
├─lib
│      studyTest.dll
│    
└─sub
        studyTest.dll

[コマンドプロンプトにおける実行履歴]
set PATH=%CD%\lib;%PATH%
> .\bin\useDLL.exe



"call_Proc"ボタンを押下。

>move .\bin\studyTest.dll .\bin\studyTest_A.dll
"call_Proc"ボタンを押下。

>move C:\Windows\SysWOW64\studyTest.dll C:\Windows\SysWOW64\studyTest_A.dll
"call_Proc"ボタンを押下。

>move C:\Windows\studyTest.dll C:\Windows\studyTest_A.dll
"call_Proc"ボタンを押下。

>move .\sub\studyTest.dll .\sub\studyTest_A.dll
"call_Proc"ボタンを押下。






DLLを使うコード
unit dllStudy;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  shlObj;

type
  TuseDLL = class(TForm)
    callProc: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Edit3: TEdit;
    Label3: TLabel;
    procedure callProcClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
    procedure updateCurDir();
  public
    { Public 宣言 }
  end;

  Type TWhereAreYou = procedure(); stdcall;

var
  useDLL: TuseDLL;
  whereAreYou : TWhereAreYou;

implementation

{$R *.dfm}


procedure TuseDLL.callProcClick(Sender: TObject);
var
  Handle : THandle;
begin
  Handle := LoadLibrary('studyTest.dll');
  if(Handle0) then begin
    @whereAreYou := GetProcAddress(Handle, 'whereAreYou');
    if(@whereAreYounil) then  whereAreYou;
    FreeLibrary(Handle);
  end;
end;

procedure TuseDLL.FormShow(Sender: TObject);
var
 cSysDir : array[0..MAX_PATH] of char;
 cWinsDir : array[0..MAX_PATH] of char;
begin
  // change current directory
  ChDir('.\Sub');
  updateCurDir;

  GetSystemDirectory(cSysDir, GetSystemDirectory(cSysDir,1)+1);
  SHGetSpecialFolderPath(Handle, cSysDir, CSIDL_SYSTEMX86, False);
  Edit2.Text := String(cSysDir);
  GetWindowsDirectory(cWinsDir, GetWindowsDirectory(cWinsDir, 1)+1);
  Edit3.Text := String(cWinsDir);
end;

procedure TuseDLL.updateCurDir;
begin
  Edit1.Text := GetCurrentDir;
end;

end.


References
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx#standard_search_order_for_desktop_applications