如何让Lazarus生成的EXE仅在Windows系统目录查找version.dll?
让Lazarus生成的EXE仅从Windows系统目录加载version.dll的方案
针对编译的EXE优先在本地目录查找version.dll、而非直接调用系统目录版本的问题,以下是几种无需静态链接的解决方法:
方法1:显式加载指定系统路径的version.dll
放弃编译器自动完成的隐式链接,改为手动加载系统目录下的version.dll,完全控制加载来源:
- 调用
GetSystemDirectory获取Windows系统目录路径; - 拼接出
version.dll的绝对路径; - 通过
LoadLibrary加载该绝对路径的DLL,再用GetProcAddress获取所需函数的地址。
示例Pascal代码:
uses Windows; var SysDir: array[0..MAX_PATH] of Char; hVersionDLL: THandle; // 以GetFileVersionInfoSizeW为例,替换成你需要的version.dll函数 GetFileVersionInfoSizeW: function(lptstrFilename: LPCWSTR; var lpdwHandle: DWORD): DWORD; stdcall; begin // 获取系统目录 GetSystemDirectory(SysDir, MAX_PATH); StrCat(SysDir, '\version.dll'); // 加载系统目录下的version.dll hVersionDLL := LoadLibrary(SysDir); if hVersionDLL <> 0 then begin // 获取函数地址 @GetFileVersionInfoSizeW := GetProcAddress(hVersionDLL, 'GetFileVersionInfoSizeW'); if Assigned(GetFileVersionInfoSizeW) then begin // 此处添加函数调用逻辑 end; // 用完释放DLL FreeLibrary(hVersionDLL); end; end;
这种方式完全绕开系统默认的DLL搜索顺序,确保只加载系统目录的版本,同时保持动态链接的特性。
方法2:修改进程的DLL搜索路径
在程序启动初期调用SetDllDirectory函数,移除当前目录的搜索优先级,让系统直接从系统目录等标准位置查找DLL:
begin // 清空额外的DLL搜索目录,仅保留系统默认的系统目录、Windows目录等 SetDllDirectory(''); Application.Initialize; // 后续程序逻辑 end;
调用SetDllDirectory('')后,系统的DLL搜索顺序会跳过当前目录,直接检查系统目录,刚好解决你遇到的「先查本地再查系统」的问题。此方法无需修改现有函数调用逻辑,只需在启动时添加一行代码。
关于LOAD_WITH_ALTERED_SEARCH_PATH的说明
你提到的LOAD_WITH_ALTERED_SEARCH_PATH选项仅配合LoadLibrary的绝对路径使用,和静态链接没有关系——它只是告诉系统:以传入的DLL路径所在目录为基准进行依赖搜索,而非当前进程目录。如果采用方法1的显式加载,若version.dll还有其他依赖,可考虑使用该选项,但单纯加载version.dll本身时,直接用绝对路径加载即可生效。
内容的提问来源于stack exchange,提问作者f.verrini
相关产品推荐
相关产品推荐

