InnoSetup DLL卸载

时间:2015-01-27 14:14:27

标签: c# dll callback inno-setup

我有一个InnoSetup,我加载了一个C#DLL。安装程序在安装结束时挂起。 我在stackoverflow上发现了一个线程,它似乎有一些很好的信息,但我没有经验可以获得所提供的信息......

InnoSetup hangs after install due to dll

我的DLL基本上做了什么:

  1. 在某些线程中解压缩* .zip文件
  2. 通过回调向innoSetup提供反馈。
  3. Inno发生了什么:

    1. 启动导出的DLL方法
    2. 接收回叫
    3. 解压缩完成后卸载DLL。
    4. 但似乎DLL永远不会被卸载。 我通过TimerEvent测试它,它每5秒触发一次,计时器永不停止。

      这是一段代码: INNO:

      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#部分使用的所有数据

2 个答案:

答案 0 :(得分:1)

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

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

正确的用法应该是:

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)然后开始

答案 1 :(得分:0)

我发现了我的设置最终挂断的原因。我无法描述原因,因为我无法查看其内容的微软来源,但我将其缩小到计时器对象。

以下是我正在做的一些背景: 我写了一个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安装程序完成的操作。 我自己在线程对象的帮助下编写了一个计时器,它比计时器更好。 此解决方案并不完美,但可以在设置过程中使用线程。

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