InnoSetup DLL 卸载

InnoSetup DLL Unload

我有一个 InnoSetup,我在其中加载了一个 C# DLL。安装程序在安装结束时挂断。 我在 Whosebug 上找到了一个线程,其中似乎有一些很好的信息,但我没有经验来获取所提供的信息...

InnoSetup hangs after install due to dll

我的 DLL 所做的基本上是:

  1. 在某些线程中解压 *.zip 文件
  2. 通过回调向 innoSetup 提供反馈。

Inno 发生了什么:

  1. 启动Exported DLL方法
  2. 收到回调
  3. 解压缩完成后卸载 DLL。

但 DLL 似乎从未卸载过。 我通过每 5 秒触发一次的 TimerEvent 对其进行了测试,并且计时器从不停止。

这是一个代码片段: 英诺:

type
TProgressCallback=procedure(progress:Integer); // ; id : String
function WrapProgressProc(callback:TProgressCallback; paramcount:integer):longword;
external 'wrapcallback@files:innocallback.dll stdcall';
function ReadZipEx(xml:String; callback:longword): longword;
external 'ReadZipEx@{src}\data\tools\ZipLib.dll stdcall loadwithalteredsearchpath';

procedure InstallData();
var
    progCallBack            : longword;
begin

    progCallBack := WrapProgressProc(@ProgressCallback,1);
    //create xml
    ReadZipEx(m_XML_String,progCallBack);
end;

procedure ProgressCallback(progress:Integer); //;id : String
begin
    pbStateZip.position := progress;
    lblState1.Caption  := IntToStr(progress);
    if(progress = 100)then begin
       UnloadDLL(ExpandConstant('{src}\data\tools\ZipLib.dll'));
       UnloadDLL(ExpandConstant('{tmp}\innocallback.dll'));
       OperationsFinished();
    end
end;

C#:

    [DllExport("ReadZipEx", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
    public static int ReadZipEx(string xml, ReportProgress repoProg)
    {
      //start threads
      //start timers which fire the callback
    }

有谁知道为什么我的设置最后会冻结,为什么 DLL 永远不会卸载或为什么它会保留 运行?我试图释放 C# 部分使用的所有数据

实际上我认为你没有正确调用 innocallback.dll - 目录不匹配(你从 {tmp} 调用它但它被声明为 @files:)。

您在 {tmp} 文件夹中有 innocallback.dll 吗?在调用 UnloadDLL 之前立即检查它。并且不需要对 UnloadDLL 进行 2 次调用。

正确的用法应该是:

procedure DllFunc; external 'DllFunc@{app}\MyDll.dll stdcall uninstallonly';

...

begin
  // Call DllFunc
  DllFunc;

  // Unload the DLL
  UnloadDLL(ExpandConstant('{app}\MyDll.dll'));

  // Now we can delete the DLL
  DeleteFile(ExpandConstant('{app}\MyDll.dll'));
end;

所以 dll 被复制到 {app} 文件夹(在 [Files] 部分)。

第二件事:

永远不要比较浮点数、进度和类似的东西是否相等。 进度可能是非线性的,因此它可能会完成,例如值为 105。

使用

if(progress >= 100)then begin

我找到了我的设置最终挂起的原因。我无法描述原因,因为我无法查看他们的东西的 Microsoft 来源,但我将其缩小到计时器对象。

这是我正在做的一些背景: 我写了一个 C# Dll 并在这个 DLL 的帮助下公开了一个静态方法 https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

在 Inno Setup 中,我在 Sherlock 软件的 InnoCallback 库的帮助下调用了这个暴露的方法 http://www.sherlocksoftware.org/page.php?id=54

我将回调方法传递给公开的方法,以便我可以接收状态更新。我在这里提供一个工作示例: Call C# DLL from Inno Setup with callback

我的 Inno Setup 的回调是从计时器调用的。 这就是问题所在。定时器对象,即使它被停止并设置为 NULL,也会继续做一些阻止 Inno Setup 完成的事情。 我在线程对象的帮助下自己写了一个计时器,它比计时器工作得更好。 此解决方案并不完美,但提供了在设置过程中使用线程的可能性。

如果以后有人有更多信息,请随时使用下面的评论部分。