2014-12-18 18 views
5

Tôi có tập lệnh Inno Setup đang chạy, trong đó tôi sử dụng innocallback.dll bởi Phần mềm Sherlock.Gọi C# DLL từ Thiết lập Inno với gọi lại

DLL này kết thúc tốt đẹp một thủ tục của tôi để nó có thể được chuyển cho C# DLL.

Tôi không muốn sử dụng DLL này, tôi muốn gọi phương thức C# đã xuất của tôi trực tiếp và chuyển đến thủ tục gọi lại.

Câu hỏi của tôi là:

Làm thế nào tôi có thể vượt qua thủ tục cài đặt Inno của tôi (@mycallback) đến C# DLL của tôi để tôi có thể sử dụng nó như tôi delegate/UnmanagedFunctionPointer?

Như tôi đã nói mã này hoạt động, nhưng tôi muốn sử dụng càng ít DLL bên ngoài càng tốt.

Đây là mã của tôi:

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; 

Và đây là C của tôi # mã

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

Trả lời

2

Không có cách nào để thả các cách sử dụng của gói Thư viện InnoCallback vì bạn không thể xác định thủ tục gọi lại với quy ước gọi điện của sự lựa chọn của bạn trong Inno Setup, bạn cũng không thể xác định một cuộc gọi lại với quy ước gọi là register (một quy ước cụ thể cho trình biên dịch Delphi) trong thư viện C# của bạn.

Do giới hạn này, bạn phải sử dụng thư viện bên ngoài, bao gồm phương thức gọi lại từ thiết lập Inno vào một hàm có quy ước gọi thư viện của bạn có thể tiêu thụ (InnoCallback sử dụng stdcall cho điều đó).

Vì vậy, những gì bạn đang yêu cầu sẽ là có thể nếu bạn đang viết thư viện của mình bằng ngôn ngữ hỗ trợ quy ước gọi điện của Delphi là register. Ra khỏi tò mò, trong Delphi bạn có thể viết ví dụ:

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. 

Và trong Inno Setup sau đó (mà không cần bất kỳ thư viện gói):

[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

Tôi chỉ thấy bạn đã nhận INNO-setup Badge vàng . Xin chúc mừng :) – Bongo