使用回调从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;