dll - 如果 DLL 有 dontcopy 标志,可以在卸载程序中调用 DLL 函数吗?

标签 dll inno-setup dllimport pascalscript

正如标题所说,我的 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/

相关文章:

c++ - 当 Matlab 中仅接受 Int32Ptr 时,以字符串形式返回错误号

c# - 将 VlcManager 与最新版本的 Vlc.DotNet 一起使用

inno-setup - 是什么原因导致消息 “Internal Error: cannot find utcompiledcode record for this version of the uninstaller”?

inno-setup - InnoSetup : If no components are selected, 返回组件页面

c# - 调用 DLL 方法时,方法的类型签名与 PInvoke 不兼容

c# - 重建后 exe/dll 的 MD5 不同

c# - 如何部署一个不断变化的DLL?

inno-setup - Inno Setup - 如何在安装过程中读取 INF 文件

c# - 尝试加载格式不正确的程序异常会随着 VS 安装而消失

c# - 将带有参数的 c# 回调方法传递给 c++ dll 会导致 System.ExecutionEngineException