加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

使用回调从Inno Setup调用C#DLL

发布时间:2020-12-15 09:47:39 所属栏目:大数据 来源:网络整理
导读:我有一个正在运行的Inno Setup脚本,其中我使用Sherlock Software的innocallback.dll. 这个DLL包装了我的一个过程,以便它可以传递给C#DLL. 我不想使用这个DLL,我想直接调用我导出的C#方法并将回调过程传递给它. 我的问题是: 如何将我的Inno安装程序(@mycallb
我有一个正在运行的Inno Setup脚本,其中我使用Sherlock Software的innocallback.dll.

这个DLL包装了我的一个过程,以便它可以传递给C#DLL.

我不想使用这个DLL,我想直接调用我导出的C#方法并将回调过程传递给它.

我的问题是:

如何将我的Inno安装程序(@mycallback)传递给我的C#DLL,以便我可以将它用作我的委托/ UnmanagedFunctionPointer?

正如我所说的这段代码有效,但我想尽量少用外部DLL.

这是我的代码:

Inno安装脚本

type
  TTimerProc=procedure();
  TProgressCallback=procedure(progress:Integer);
? ? 
function WrapProgressProc(callback:TProgressCallback; paramcount:integer):longword;
  external 'wrapcallback@files:innocallback.dll stdcall';

function Test(callback:longword): String;
  external 'Test@files:ExposeTestLibrary.dll stdcall';

var
  endProgram : Boolean;

procedure mycallback(progress:Integer);
begin
  MsgBox(IntToStr(progress),mbInformation,MB_OK);?
  if progress > 15 then
  begin
    endProgram := True;
  end
end;
??
function InitializeSetup:boolean;
var
  progCallBack ? : longword;
  callback ? ? ? : longword;
  msg ? ? ? ? ? ?: longword;
  msg2 ? ? ? ? ? : widestring;
begin
  endProgram := False;
  progCallBack:= WrapProgressProc(@mycallback,1); //Our proc has 1 arguments
  Test(progCallBack);
  result:=true;
end;

这是我的C#代码

public class TestClass
{
? ? [UnmanagedFunctionPointer(CallingConvention.StdCall)]
? ? public delegate void ReportProgress(uint progress);

? ? public static ReportProgress m_reportProgess;
? ? static uint m_iProgress;
? ??
? ? [DllExport("Test",CallingConvention = CallingConvention.StdCall)]
? ? static int Test(ReportProgress rProg)
? ? {
? ? ? ? m_iProgress = 0;
? ? ? ? m_reportProgess = rProg;
? ? ? ? System.Timers.Timer pTimer = new System.Timers.Timer();
? ? ? ? pTimer.Elapsed += aTimer_Elapsed;
? ? ? ? pTimer.Interval = 1000;
? ? ? ? pTimer.Enabled = true;
? ? ? ? GC.KeepAlive(pTimer);
? ? ? ? return 0;
? ? }

? ? static void aTimer_Elapsed(object sender,System.Timers.ElapsedEventArgs e)
? ? {
? ? ? ? m_iProgress++;
? ? ? ? m_reportProgess(m_iProgress);
? ? }
}

解决方法

没有办法放弃包装InnoCallback库的用法,因为你根本无法在Inno Setup中使用你选择的调用约定来定义回调过程,也无法使用寄存器调用约定定义回调(Delphi编译器专用的回调)在你的C#库中.

由于这个限制,你必须使用一个外部库,它将Inno Setup的回调方法包装到一个具有库可以使用的调用约定的函数中(InnoCallback使用stdcall).

因此,如果您使用支持Delphi注册调用约定的语言编写库,那么您所要求的就是可能的.出于好奇,在Delphi你可以写例如:

library MyLib;

type
  TMyCallback = procedure(IntParam: Integer; StrParam: WideString) of object;

procedure CallMeBack(Callback: TMyCallback); stdcall;
begin
  Callback(123,'Hello!');
end;

exports
  CallMeBack;

begin
end.

然后在Inno Setup中(没有任何包装库):

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}My Program

[Files]
Source: "MyLib.dll"; Flags: dontcopy
[Code]
type
  TMyCallback = procedure(IntParam: Integer; StrParam: WideString);

procedure CallMeBack(Callback: TMyCallback);
  external 'CallMeBack@files:mylib.dll stdcall';

procedure MyCallback(IntParam: Integer; StrParam: WideString);
begin
  MsgBox(Format('IntParam: %d; StrParam: %s',[IntParam,StrParam]),MB_OK);
end;

procedure InitializeWizard;
begin
  CallMeBack(@MyCallback);
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读