正如标题所说,我的 DLL 中需要一个函数,我需要在卸载时调用该函数。
DLL 是这样包含的
#define myProgData "C:\ProgramData\Foo\Bar"
[Files]
Source: "mydll.dll"; Flags: dontcopy
我在安装时已经使用了一个函数,现在我想知道是否可以使用相同的 DLL 进行卸载,或者是否必须复制该 DLL 以便卸载程序可以访问它?
我已经尝试过一个简单的调用,但得到了
Could not call proc - Exception
所以我正在寻找这个原因。
我尝试将 DLL 从安装程序中复制出来,调用效果非常好。
这是脚本的样子
[Files]
Source: "myDll.dll"; Flags: dontcopy;
(...)
[Code]
function myUninstallFunction(foo: Integer): Boolean;
external 'myFunction@{#myProgData}myDll.dll stdcall uninstallonly';
这样使用
function InitializeUninstall(): Boolean;
begin
if myUninstallFunction(1) then
begin
MsgBox(ExpandConstant('{cm:uninstallFail}'), mbError, MB_OK);
Result := false;
end;
(...)
end;
我也尝试过使用另一个事件过程,例如CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
.
最佳答案
您无法从卸载程序调用嵌入在安装程序中的 DLL,因为在卸载时,卸载程序不知道安装程序位置(并且它可能不再存在)。
可以将 DLL 嵌入到卸载程序中,但工作量更大。请参阅我对 How keep uninstall files inside uninstaller? 的回答
除此之外,没有比您已经找到的更好的解决方案了:
- 在某处安装 DLL
- 并在卸载代码中引用已安装 DLL 的路径。
- 使用
UnloadDLL
卸载已加载的DLL,以便您可以将其删除。 (我认为 .NET 汇编 DLL 无法卸载。对于那些您可以在加载之前将 DLL 复制到临时文件夹,以便可以删除已安装的副本。请参阅 Load external DLL for uninstall process in Inno Setup )
一些背景信息来解释您所遇到的行为:
在 external
声明中提供了 files:
前缀,使 Inno Setup 在需要该函数时自动提取 DLL,并自动删除提取的 DLL。
参见Pascal Scripting: Using DLLs :
During Setup, a special 'files:' prefix may also be used to instruct Setup to automatically extract one or more DLLs from the [Files] section before loading the first DLL.
示例:
procedure MyDllFuncSetup(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:MyDll.dll stdcall setuponly';
但它在卸载程序中不起作用。
您可以看到,即使是官方示例 CodeDll.iss
也使用 files:
作为安装程序函数,但诉诸于使用已安装的 DLL ({app }\
) 用于卸载程序功能:
[Files]
...
; Install our DLL to {app} so we can access it at uninstall time
; Use "Flags: dontcopy" if you don't need uninstall time access
Source: "MyDll.dll"; DestDir: "{app}"
[Code]
...
procedure MyDllFuncSetup(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:MyDll.dll stdcall setuponly';
procedure MyDllFuncUninst(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@{app}\MyDll.dll stdcall uninstallonly';
甚至 Inno Setup 源代码也证实了这一点(Projects\main.pas
函数 CodeRunnerOnDllImport
):
if Pos('files:', DllName) = 1 then begin
if IsUninstaller then begin
{ Uninstall doesn't do 'files:' }
DllName := '';
ForceDelayLoad := True;
这解释了“无法调用 proc - 异常”,因为 Inno Setup 的行为就像未指定 DLL 名称,但存在 delayload
标志。卸载程序找不到 DLL,并且您会收到神秘的错误消息(正如您通常仅使用 delayload
标志时得到的那样)。
您还可以检查使用 files:
和 uninstallonly
是否可以实现
"uninstallonly" cannot be used with "files:"
关于dll - 如果 DLL 有 dontcopy 标志,可以在卸载程序中调用 DLL 函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32782610/