Inno Setup:将 DLL 放在子目录中
Inno Setup: Put DLLs in a subdirectory
我想将依赖项(几个 DLL 文件)复制到一个单独的子目录中。安装我的程序后,目录结构如下所示:
- dlls/
- a.dll
- b.dll
- 样本/
- pg.exe
我脚本的相关部分如下:
[Dirs]
Name: "{app}\sample"
Name: "{app}\dll"
[Files]
Source: "pg.exe"; DestDir: "{app}"; Flags: ignoreversion
; icon file
;Source: "pg.ico"; DestDir: "{app}"
; sample ini and geoemtry file
Source: "geometry.xml"; DestDir: "{app}\sample"
Source: "ini.xml"; DestDir: "{app}\sample"
; DLL
Source: "a.DLL"; DestDir: "{app}\dll"; Flags: onlyifdoesntexist
Source: "b.DLL"; DestDir: "{app}\dll"; Flags: onlyifdoesntexist
当我在 VM 中测试我的安装程序时,我收到一条错误消息,提示未找到 a.DLL。如果我只是将 a.DLL
从 dll/
复制到可执行文件的目录,问题很快就解决了。
- 是否有必要将所有dll与可执行文件放在同一级别?
- 或者有没有办法让可执行文件在子目录 dll/ 中找到它的依赖项?
如果你使用的是隐式DLL链接,那么只有几个目录
您可以在其中放置必要的 DLL 文件。假设 SafeDllSearchMode
开启(这是自 Window XP SP2 以来的默认设置),Windows 加载程序按以下顺序搜索 DLL:
- 你的可执行文件所在的目录
- Windows目录
- Windows系统目录
- 当前工作目录
- PATH 环境变量中列出的目录
有关搜索顺序的详细信息,请参阅 https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx
如果您使用这种类型的链接,我建议您将 DLL 放在
与您的可执行文件相同的目录。
另一方面,如果您使用 LoadLibrary
显式链接到这些 DLL 或
LoadLibraryEx
API,您可以执行以下操作:
- 您可以调用
AddDllDirectory
并将包含您的目录的路径传递给它
DLL。确保在加载库之前调用此函数,并确保
使用带有标志 LOAD_LIBRARY_SEARCH_USER_DIRS
. 的 LoadLibraryEx
加载库
- 您可以使用
GetModuleFileName
函数检索可执行文件的路径,然后
用它来构造 DLL 的绝对路径,并在调用 LoadLibrary(Ex)
. 时使用这些路径
- 您可以在调用
LoadLibrary(Ex)
之前调用 SetDllDirectory
。这个问题
方法是每次调用SetDllDirectory
函数时,替换目录
在之前的 SetDllDirectory
调用中指定。如果您不小心,这可能会导致问题
因为代码的其他部分可能会调用 SetDllDirectory
并在加载 DLLs 时导致失败
我想将依赖项(几个 DLL 文件)复制到一个单独的子目录中。安装我的程序后,目录结构如下所示:
- dlls/
- a.dll
- b.dll
- 样本/
- pg.exe
我脚本的相关部分如下:
[Dirs]
Name: "{app}\sample"
Name: "{app}\dll"
[Files]
Source: "pg.exe"; DestDir: "{app}"; Flags: ignoreversion
; icon file
;Source: "pg.ico"; DestDir: "{app}"
; sample ini and geoemtry file
Source: "geometry.xml"; DestDir: "{app}\sample"
Source: "ini.xml"; DestDir: "{app}\sample"
; DLL
Source: "a.DLL"; DestDir: "{app}\dll"; Flags: onlyifdoesntexist
Source: "b.DLL"; DestDir: "{app}\dll"; Flags: onlyifdoesntexist
当我在 VM 中测试我的安装程序时,我收到一条错误消息,提示未找到 a.DLL。如果我只是将 a.DLL
从 dll/
复制到可执行文件的目录,问题很快就解决了。
- 是否有必要将所有dll与可执行文件放在同一级别?
- 或者有没有办法让可执行文件在子目录 dll/ 中找到它的依赖项?
如果你使用的是隐式DLL链接,那么只有几个目录
您可以在其中放置必要的 DLL 文件。假设 SafeDllSearchMode
开启(这是自 Window XP SP2 以来的默认设置),Windows 加载程序按以下顺序搜索 DLL:
- 你的可执行文件所在的目录
- Windows目录
- Windows系统目录
- 当前工作目录
- PATH 环境变量中列出的目录
有关搜索顺序的详细信息,请参阅 https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx
如果您使用这种类型的链接,我建议您将 DLL 放在 与您的可执行文件相同的目录。
另一方面,如果您使用 LoadLibrary
显式链接到这些 DLL 或
LoadLibraryEx
API,您可以执行以下操作:
- 您可以调用
AddDllDirectory
并将包含您的目录的路径传递给它 DLL。确保在加载库之前调用此函数,并确保 使用带有标志LOAD_LIBRARY_SEARCH_USER_DIRS
. 的 - 您可以使用
GetModuleFileName
函数检索可执行文件的路径,然后 用它来构造 DLL 的绝对路径,并在调用LoadLibrary(Ex)
. 时使用这些路径
- 您可以在调用
LoadLibrary(Ex)
之前调用SetDllDirectory
。这个问题 方法是每次调用SetDllDirectory
函数时,替换目录 在之前的SetDllDirectory
调用中指定。如果您不小心,这可能会导致问题 因为代码的其他部分可能会调用SetDllDirectory
并在加载 DLLs 时导致失败
LoadLibraryEx
加载库