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

我有一个正在运行的Inno Setup脚本,其中我使用Sherlock Software的innocallback.dll。

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

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

我的问题是:

如何将我的Inno安装程序( @mycallback )传递给我的C#DLL,以便我可以将它用作我的delegate / 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);  } } 

由于您根本无法在Inno Setup中使用您选择的调用约定来定义回调过程,也无法使用register调用约定(Delphi编译器特有的约束)来定义回调过程,因此无法放弃包装InnoCallback库的使用。在你的C#库中。

由于此限制,您必须使用外部库,该库将Inno Setup的回调方法包装到具有库可以使用的调用约定的函数中(InnoCallback使用stdcall )。

因此,如果您使用支持Delphi register调用约定的语言编写库,那么您所要求的就是可能的。 出于好奇,在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]), mbInformation, MB_OK); end; procedure InitializeWizard; begin CallMeBack(@MyCallback); end;