通过回调从Inno Setup调用C#DLL

邦戈

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

该DLL包装了我的过程,以便可以将其传递给C#DLL。

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

我的问题是:

如何将Inno Setup过程(@mycallback)传递给C#DLL,以便可以将其用作delegate/ UnmanagedFunctionPointer

正如我说的那样,该代码有效,但我想使用尽可能少的外部DLL。

这是我的代码:

Inno安装脚本

type
  TTimerProc=procedure();
  TProgressCallback=procedure(progress:Integer);
    
function WrapProgressProc(callback:TProgressCallback; paramcount:integer):longword;
  external '[email protected]:innocallback.dll stdcall';

function Test(callback:longword): String;
  external '[email protected]: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);
    }
}
TLama

此答案在Inno Setup 6中不再有效。有关最新解决方案,请参阅我的(@MartinPrikryl)答案。

没有办法放弃包装的InnoCallback库的用法,因为您根本无法在Inno Setup中使用您选择的调用约定来定义回调过程,也不能在以下情况下使用调用约定来定义回调register(特定于Delphi编译器的回调):您的C#库。

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

因此,如果您使用支持Delphiregister调用约定的语言编写库,则可能会要求您出于好奇,您可以在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 '[email protected]: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;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章