2014-12-18 24 views
5

Sherlock Software tarafından innocallback.dll kullandığım çalışan bir Inno Setup komut dosyası var.Geri Çağırma ile Inno Kurulum gelen C# DLL çağrısı

Bu DLL, bir C# DLL dosyasına geçirilebilmesi için benimki bir prosedürü tamamlar.

Bu DLL'yi kullanmak istemiyorum, verilen C# yöntemimi doğrudan aramak ve geri arama yordamına iletmek istiyorum.

Sorum şu:

benim delegate/UnmanagedFunctionPointer olarak kullanabilirsiniz böylece benim C# DLL benim Inno Setup prosedürünü (@mycallback) geçebilir nasıl?

Bu kod çalıştığını söylediğim gibi, ancak olabildiğince az dış DLL kullanmak istiyorum. İşte

benim kodudur:

Inno Setup Script

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; 

Ve bu sarma kullanımını bırakmak için bir yolu yoktur benim C# kodu

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); 
    } 
} 

cevap

2

olduğunu InnoCallback kütüphanesi, arama kuralı ile bir geri çağırma prosedürünü tanımlayamazsınız. Inno Setup'taki seçiminiz için, C# kitaplığınızda register çağrı kuralı (Delphi derleyicisine özgü olan) ile bir geri arama tanımlayabilirsiniz.

Bu sınır nedeniyle, Inno Kurulumu'ndan geri arama yöntemini kitaplığınızın kullanabileceği bir çağrı sözleşmesiyle bir işleve dönüştüren harici bir kitaplık kullanmanız gerekir (InnoCallback, bunun için stdcall kullanır).

Yani, kitaplığınızı Delphi'nin register çağrı kuralını destekleyen bir dilde yazıyor olmanız durumunda, istediğiniz şey mümkün olabilir.

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. 

Sonra Inno Setup içinde (herhangi bir sarma kütüphanesinde olmadan): meraktan, Delphi size örneğin yazabilirsiniz

[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; 
+1

Sadece Inno-kurulum altın Rozet var gördü . Tebrik ederiz :) – Bongo