在 Inno Setup 中为卸载过程加载外部 DLL

Load external DLL for uninstall process in Inno Setup

我正在尝试加载 VclStylesInno.dll Inno Setup 的卸载形式。 下一个代码在 [Code] 部分的中间声明:

procedure uLoadVCLStyle(VClStyleFile: String);
    external 'LoadVCLStyleW@{app}/VclStylesInno.dll stdcall';

但是我遇到了一个错误

An attempt was made to expand the "app" constant before it was initialized

为卸载过程加载 DLL 的最佳方法是什么?

我假设您在启动安装程序时遇到错误,而不是卸载程序。

安装程序启动时,{app}显然是未知的。

但是因为你只需要导入卸载程序,它知道 {app},你可以添加 uninstallonly option:

procedure uLoadVCLStyle(VClStyleFile: String); 
  external 'LoadVCLStyleW@{app}\VclStylesInno.dll stdcall uninstallonly';

虽然它并没有真正的帮助,因为卸载程序会想要删除 DLL,但失败了,因为它已将 DLL 自身锁定。

解决方法很简单,按照官方的instructions for uninstalling the VCL Styles for Inno Setup.

您基本上需要将 DLL 安装在 {app} 之外的其他位置,并在卸载时留下 DLL。这实际上是一个丑陋的解决方案,恕我直言,这并不能证明样式化的卸载程序是合理的。但这是你的选择。


按照您的建议,您可以将 DLL 复制到 Windows 临时文件夹,从那里加载它并希望 Windows 最终在临时目录清理期间删除 DLL。

应该这样做(注意 delayload option):

[Files]
Source: VclStylesInno.dll; DestDir: {app}
Source: skin.vsf; DestDir: {app}
[Code]

procedure LoadVCLStyle_UnInstall(VClStyleFile: String); 
  external 'LoadVCLStyleW@{%TEMP}\VclStylesInno.dll stdcall uninstallonly delayload';

function InitializeUninstall: Boolean;
begin
  if FileCopy(ExpandConstant('{app}\VclStylesInno.dll'),
              ExpandConstant('{%TEMP}\VclStylesInno.dll'), False) and
     FileCopy(ExpandConstant('{app}\skin.vsf'),
              ExpandConstant('{%TEMP}\skin.vsf'), False) then
  begin
    LoadVCLStyle_UnInstall(ExpandConstant('{%TEMP}\skin.vsf'));
  end;
end;

虽然我没有测试它,但使用 {tmp} 而不是 {%TEMP} 可能更好(文件可能会在卸载完成后立即被卸载程序父进程删除 – 而且你不会干扰可能要将 VclStylesInno.dll 存储到 %TEMP%) 的其他进程。


另一种解决方案(更好但实施起来更复杂),请参阅
How keep uninstall files inside uninstaller?