-1

I have an InnoSetup where i Load a C# DLL. The Installer hangs up in the end of the setup. I found a thread on stackoverflow which seems to have some good informations in it, but i am to unexperienced to get the information provided...

InnoSetup hangs after install due to dll

What my DLL does is basicly:

  1. Unzip *.zip files in some threads
  2. provide feedback to innoSetup via a callback.

What in Inno happens:

  1. Start the Exported DLL method
  2. Receive the callback
  3. When the unzipping is done Unload the DLL.

But it seems the DLL is never unloaded. I tested it via a TimerEvent which is fired every 5 seconds and the timer never stops.

Here is a code snippet: 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
    }

Does anybody know why my setup freezes in the end and why the DLL is never unloaded or why it keeps running ? i tried to release all data which the C# part uses

Community
  • 1
  • 1
Bongo
  • 2,933
  • 5
  • 36
  • 67

2 Answers2

1

Actually I think you are not calling innocallback.dll correctly - there is directory mismatch (you are calling it from {tmp} but it is declared as @files:).

Do you have innocallback.dll in {tmp} folder? Check it immediately before calling UnloadDLL. And there is no need to have 2 calls to UnloadDLL.

The correct usage should be:

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;

So the dll is copied into {app} folder (in [Files] section).

The second thing:

Never compare floating numbers, progress and similar stuff for equality. The progress may be non linear so it may finish e.g. at value 105.

Use

if(progress >= 100)then begin

Slappy
  • 5,250
  • 1
  • 23
  • 29
  • If i have two DLL's do i really have to call unload DLL only once ? that seems to me a little bit strange. With the progress you are right, i should check if it is above or equal to 100 . For the purpose of test i created a version which only gives me 100 as testvalue so i only compared it to that ;) – Bongo Jan 29 '15 at 12:50
  • No, you are right you need 2 calls for 2 separate dlls, my bad - I did not notice you are unloading two different dlls :) – Slappy Jan 29 '15 at 13:11
  • UnloadDLL() does not work in my usecase. See this related question: https://stackoverflow.com/questions/49447374/innosetup-unable-to-unload-and-delete-a-dll-required-by-install-from-the-tmp – Bug Raptor Mar 23 '18 at 10:29
0

I've found the reason why my setup hangs up in the end. I can't describe why, because i can't look into the microsoft sources of their stuff but i narrowed it down to the timer object.

Here is some background what i am doing: I wrote a C# Dll and exposed a static method with the help of this DLL https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

From Inno Setup I call this exposed method with the help of the InnoCallback library by sherlock software http://www.sherlocksoftware.org/page.php?id=54

I pass a callback method to my exposed method so that i can receive status updates. Here i provide a working example: Call C# DLL from Inno Setup with callback

The callback of my Inno Setup was called from a timer. And here is the problem. The timer object, even if it is stopped and set to NULL, keeps doing something that blocks the Inno Setup from finishing. I wrote a timer myself with the help of the thread object which works better then the timer. This solution is not perfect but provides the possibility to work with threads during the setup process.

If somebody in the future has further infos please feel free to use the comment section below.

Community
  • 1
  • 1
Bongo
  • 2,933
  • 5
  • 36
  • 67
  • 1
    Do you remember when I [`told you`](http://stackoverflow.com/questions/28047332/inno-setup-semaphore-non-gui-blocking#comment44479754_28047332) to not access UI controls from a worker thread ? This might be the consequence. You would have to synchronize your code with the main thread somehow. You cannot just come up with a callback invoked from a worker thread and access main thread's controls. That's what you cannot do even in pure C# app. – TLama Feb 02 '15 at 10:04
  • I Know you were right :( . But thanks for remembering me that i was wrong :D – Bongo Feb 02 '15 at 10:13
  • @TLama Btw. it works now with a Thread but my Finish screen resets it's graphics in the end. But no freezing whatsoever. I am thinking how i could do this in inno setup alone but inno setup doesn't provide Threads. When i have a solution i provide it here – Bongo Feb 02 '15 at 11:44