InnoSetup DLL 卸载
InnoSetup DLL Unload
我有一个 InnoSetup,我在其中加载了一个 C# DLL。安装程序在安装结束时挂断。
我在 Whosebug 上找到了一个线程,其中似乎有一些很好的信息,但我没有经验来获取所提供的信息...
InnoSetup hangs after install due to dll
我的 DLL 所做的基本上是:
- 在某些线程中解压 *.zip 文件
- 通过回调向 innoSetup 提供反馈。
Inno 发生了什么:
- 启动Exported DLL方法
- 收到回调
- 解压缩完成后卸载 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 完成的事情。
我在线程对象的帮助下自己写了一个计时器,它比计时器工作得更好。
此解决方案并不完美,但提供了在设置过程中使用线程的可能性。
如果以后有人有更多信息,请随时使用下面的评论部分。
我有一个 InnoSetup,我在其中加载了一个 C# DLL。安装程序在安装结束时挂断。 我在 Whosebug 上找到了一个线程,其中似乎有一些很好的信息,但我没有经验来获取所提供的信息...
InnoSetup hangs after install due to dll
我的 DLL 所做的基本上是:
- 在某些线程中解压 *.zip 文件
- 通过回调向 innoSetup 提供反馈。
Inno 发生了什么:
- 启动Exported DLL方法
- 收到回调
- 解压缩完成后卸载 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 完成的事情。 我在线程对象的帮助下自己写了一个计时器,它比计时器工作得更好。 此解决方案并不完美,但提供了在设置过程中使用线程的可能性。
如果以后有人有更多信息,请随时使用下面的评论部分。